1. 程式人生 > >spring中註解處理框架解析----原始碼實現

spring中註解處理框架解析----原始碼實現

@Autowired和@Resource的區別:

在Java中使用@Autowired和@Resource註解進行裝配,這兩個註解分別是:
1、@Autowired按照預設型別(類名稱)裝配依賴物件,預設情況下它要求依賴物件必須存在,如果允許為null,可以設定它的required屬性為false
如果我們按名稱裝配,可以結合@Qualifie註解一起使用。
如:
@Autowired @qualifie("personDaoBean")
private PersonDaoBean personDaoBean;

@Resource預設按照名稱(name="test")進行裝配,名稱可以通過@resource的name屬性設定,當找不到與名稱匹配的bean才會按型別裝配

注意:如果沒有指定name屬性,並且安裝預設的名稱依然找不到依賴物件時,@Resource會回退到按型別裝配。但一旦指定了name屬性,就只能按名稱裝配了。

下面的示例來簡單的講述spring註解原理:

本例實現了在set方法上和在欄位屬性上註解的處理解析。

1、定義註解

Java程式碼  收藏程式碼
  1. package com.yt.annotation;  
  2. import java.lang.annotation.ElementType;  
  3. import java.lang.annotation.Retention;  
  4. import java.lang.annotation.RetentionPolicy;  
  5. import java.lang.annotation.Target;  
  6. /** 
  7.  * @Description:定義註解 
  8.  * @ClassName: ZxfResource 
  9.  * @Project: spring-aop 
  10.  * @Author: zxf 
  11.  * @Date: 2011-6-7 
  12.  */  
  13. // 在執行時執行  
  14. @Retention(RetentionPolicy.RUNTIME)  
  15. // 註解適用地方(欄位和方法)  
  16. @Target({ ElementType.FIELD, ElementType.METHOD })  
  17. public @interface ZxfResource {  
  18.     //註解的name屬性  
  19.     public String name() default "";  
  20. }  

 2、帶有註解的服務類

Java程式碼  收藏程式碼
  1. package com.yt.annotation;  
  2. /** 
  3.  * @Description: 帶有註解的服務 
  4.  * @ClassName: UserDaoImpl 
  5.  * @Project: spring-aop 
  6.  * @Author: zxf 
  7.  * @Date: 2011-6-7 
  8.  */  
  9. public class UserServiceImpl {  
  10.     public UserDaoImpl userDao;  
  11.     public User1DaoImpl user1Dao;  
  12.     // 欄位上的註解,可以配置name屬性  
  13.     @ZxfResource  
  14.     public User2DaoImpl user2Dao;  
  15.     // set方法上的註解,帶有name屬性  
  16.     @ZxfResource(name = "userDao")  
  17.     public void setUserDao(UserDaoImpl userDao) {  
  18.         this.userDao = userDao;  
  19.     }  
  20.     // set方法上的註解,沒有配置name屬性  
  21.     @ZxfResource  
  22.     public void setUser1Dao(User1DaoImpl user1Dao) {  
  23.         this.user1Dao = user1Dao;  
  24.     }  
  25.     public void show() {  
  26.         userDao.show();  
  27.         user1Dao.show1();  
  28.         user2Dao.show2();  
  29.         System.out.println("這裡是Service方法........");  
  30.     }  
  31. }  

 3、要注入的DAO

Java程式碼  收藏程式碼
  1. package com.yt.annotation;  
  2. /** 
  3.  * @Description: 要注入的DAo類 
  4.  * @ClassName: UserDaoImpl 
  5.  * @Project: spring-aop 
  6.  * @Author: zxf 
  7.  * @Date: 2011-6-7 
  8.  */  
  9. public class UserDaoImpl {  
  10.     String name ;  
  11.     public void show(){  
  12.         System.out.println("這裡是dao方法........");  
  13.     }  
  14. }  
Xml程式碼  收藏程式碼
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans>  
  3.     <bean id = "userDao" class="com.yt.annotation.UserDaoImpl" />  
  4.     <bean id = "user1Dao" class="com.yt.annotation.User1DaoImpl" />  
  5.     <bean id = "user2Dao" class="com.yt.annotation.User2DaoImpl" />  
  6.     <bean id = "userService" class = "com.yt.annotation.UserServiceImpl" />  
  7. </beans>  

 4、註解處理器

Java程式碼  收藏程式碼
  1. package com.yt.annotation;  
  2. import java.beans.Introspector;  
  3. import java.beans.PropertyDescriptor;  
  4. import java.lang.reflect.Field;  
  5. import java.lang.reflect.Method;  
  6. import java.util.ArrayList;  
  7. import java.util.HashMap;  
  8. import java.util.Iterator;  
  9. import java.util.List;  
  10. import java.util.Map;  
  11. import org.apache.log4j.Logger;  
  12. import org.dom4j.Document;  
  13. import org.dom4j.DocumentException;  
  14. import org.dom4j.Element;  
  15. import org.dom4j.io.SAXReader;  
  16. /** 
  17.  * @Description: spring中的註解原理 
  18.  * @ClassName: ClassPathXMLApplicationContext 
  19.  * @Project: spring-aop 
  20.  * @Author: zxf 
  21.  * @Date: 2011-6-3 
  22.  */  
  23. public class ClassPathXMLApplicationContext {  
  24.     Logger log = Logger.getLogger(ClassPathXMLApplicationContext.class);  
  25.     List<BeanDefine> beanList = new ArrayList<BeanDefine>();  
  26.     Map<String, Object> sigletions = new HashMap<String, Object>();  
  27.     public ClassPathXMLApplicationContext(String fileName) {  
  28.         //讀取配置檔案中管理的bean  
  29.         this.readXML(fileName);  
  30.         //例項化bean  
  31.         this.instancesBean();  
  32.         //註解處理器  
  33.         this.annotationInject();  
  34.     }  
  35.     /** 
  36.      * 讀取Bean配置檔案 
  37.      * @param fileName 
  38.      * @return 
  39.      */  
  40.     @SuppressWarnings("unchecked")  
  41.     public void readXML(String fileName) {  
  42.         Document document = null;  
  43.         SAXReader saxReader = new SAXReader();  
  44.         try {  
  45.             ClassLoader classLoader =   
  46.                 Thread.currentThread().getContextClassLoader();  
  47.             document = saxReader.read(classLoader.getResourceAsStream(fileName));  
  48.             Element beans = document.getRootElement();  
  49.             for (Iterator<Element> beansList = beans.elementIterator();   
  50.                 beansList.hasNext();) {  
  51.                 Element element = beansList.next();  
  52.                 BeanDefine bean = new BeanDefine(  
  53.                         element.attributeValue("id"),  
  54.                         element.attributeValue("class"));  
  55.                 beanList.add(bean);  
  56.             }  
  57.         } catch (DocumentException e) {  
  58.             log.info("讀取配置檔案出錯....");  
  59.         }  
  60.     }  
  61.     /** 
  62.      * 例項化Bean 
  63.      */  
  64.     public void instancesBean() {  
  65.         for (BeanDefine bean : beanList) {  
  66.             try {  
  67.                 sigletions.put(bean.getId(),   
  68.                         Class.forName(bean.getClassName()).newInstance());  
  69.             } catch (Exception e) {  
  70.                 log.info("例項化Bean出錯...");  
  71.             }  
  72.         }  
  73.     }  
  74.     /** 
  75.      * 註解處理器 
  76.      * 如果註解ZxfResource配置了name屬性,則根據name所指定的名稱獲取要注入的例項引用, 
  77.      * 如果註解ZxfResource;沒有配置name屬性,則根據屬性所屬型別來掃描配置檔案獲取要 
  78.      * 注入的例項引用 
  79.      *  
  80.      */  
  81.     public void annotationInject(){  
  82.         for(String beanName:sigletions.keySet()){  
  83.             Object bean = sigletions.get(beanName);  
  84.             if(bean!=null){  
  85.                 this.propertyAnnotation(bean);  
  86.                 this.fieldAnnotation(bean);  
  87.             }  
  88.         }  
  89.     }  
  90.     /** 
  91.      * 處理在set方法加入的註解 
  92.      * @param bean 處理的bean 
  93.      */  
  94.     public void propertyAnnotation(Object bean){  
  95.         try {  
  96.             //獲取其屬性的描述  
  97.             PropertyDescriptor[] ps =   
  98.                 Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();  
  99.             for(PropertyDescriptor proderdesc : ps){  
  100.                 //獲取所有set方法  
  101.                 Method setter = proderdesc.getWriteMethod();  
  102.                 //判斷set方法是否定義了註解  
  103.                 if(setter!=null && setter.isAnnotationPresent(ZxfResource.class)){  
  104.                     //獲取當前註解,並判斷name屬性是否為空  
  105.                     ZxfResource resource = setter.getAnnotation(ZxfResource.class);  
  106.                     String name ="";  
  107.                     Object value = null;  
  108.                     if(resource.name()!=null&&!"".equals(resource.name())){  
  109.                         //獲取註解的name屬性的內容  
  110.                         name = resource.name();  
  111.                         value = sigletions.get(name);  
  112.                     }else//如果當前註解沒有指定name屬性,則根據型別進行匹配  
  113.                         for(String key : sigletions.keySet()){  
  114.                             //判斷當前屬性所屬的型別是否在配置檔案中存在  
  115. 相關推薦

    spring註解處理框架解析----原始碼實現

    @Autowired和@Resource的區別: 在Java中使用@Autowired和@Resource註解進行裝配,這兩個註解分別是: 1、@Autowired按照預設型別(類名稱)裝配依賴物件,預設情況下它要求依賴物件必須存在,如果允許為null,可以設定它的r

    spring註解實現原理

    下面的示例來簡單的講述spring註解原理: 本例實現了在set方法上和在欄位屬性上註解的處理解析。 1、定義註解 Java程式碼 複製程式碼 收藏程式碼 1.package com.yt.annotation;  2.  3.import java.lang.an

    SpringMVCservlet處理http請求原始碼解析

        Spring MVC的核心控制器為Servlet,所有訪問服務端的請求都將由servlet攔截接受,並進行相應處理最終進行返回。下面我們來看看它究竟是怎麼做的。     SpringMVC中的Servl

    spring註解實現原理,幫助理解@autowired @resource區別

    package com.yt.annotation; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lan

    Spring註解實現原理-Autowired和Resource的區別

    @Autowired和@Resource的區別: 在Java中使用@Autowired和@Resource註解進行裝配,這兩個註解分別是: 1、@Autowired按照預設型別(類名稱)裝配依賴物件,預設情況下它要求依賴物件必須存在,如果允許為null,可以

    Spring註解

    name return resource 處理 ransac ack json attr servlet @Autowired :spring註解 @Resource :J2EE註解 @Transactional(rollbackFor=Exception.class)

    spring 註解的詳細解釋之@Responsebody與@RequestBody

    可用 gif com .com profile 而是 ping get orm 1、@responseBoby @Responsebody與@RequestBody 一、預備知識:@RequestMapping RequestMapping是一個用來處理請求地

    spring的Ioc技術是怎樣實現解耦的 原文地址 : http://blog.csdn.net/liang5603/article/details/52002994

    ioc容器 可能 深入 修改 知識 動態 出現 工廠方法 邏輯 1. IoC理論的背景我們都知道,在采用面向對象方法設計的軟件系統中,它的底層實現都是由N個對象組成的,所有的對象通過彼此的合作,最終實現系統的業務邏輯。圖1:軟件系統中耦合的對象如果我們打開機械式手表的後蓋,

    實戰 :Spring MVC + 註解 +SqlServer 框架搭建及詳解

    原始碼下載:http://download.csdn.NET/detail/u010469432/6786687 https://blog.csdn.net/u010469432/article/details/17587699 先說一下Spring3 MVC的優點: spring&nb

    Spring註解注入bean和配置檔案注入bean

    註解的方式確實比手動寫xml檔案注入要方便快捷很多,省去了很多不必要的時間去寫xml檔案 按以往要注入bean的時候,需要去配置一個xml,當然也可以直接掃描包體,用xml注入bean有以下方法: 1 <?xml version="1.0" encoding="UTF-8"?> 2

    spring boot 自定義引數解析實現form表單型別請求或位址列請求引數下劃線轉駝峰屬性

    一、定義引數解析註解 @Target(value = ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) public @interface ParameterModel { } 二、定義抽象類AbstractCustomiz

    Spring Dataflow批處理框架在OCP上的部署

    詳細參考 https://donovanmuller.blog/spring-cloud-dataflow-server-openshift/docs/1.2.1.RELEASE/reference/htmlsingle/   注意事項: Openshift上需要部署service cata

    spring MVC執行過程分析與原始碼實現

    spring mvc 啟動過程可分為如下3步: =============================================                             web.xml                           Dispa

    【學習排序】 Learning to RankPointwise關於PRank演算法原始碼實現

    最近終於忙完了Learning to Rank的作業,同時也學到了很多東西.我準備寫幾篇相關的文章簡單講述自己對它的理解和認識.第一篇準備講述的就是Learning to Rank中Pointwise的認識及PRank演算法的實現.主要從以下四個方面進行講述:     1.學

    Spring註解@Transactional在oracl和mysql差異

    嘿嘿 !從今天開始圖圖開始寫部落格啦 這是圖圖的第一個部落格 ,不足之處請大家指出,共同進步。 @Transactional是Spring中的事務註解,其引數為readOnly用於設定當前事務是否為只讀事務,設定為true表示只讀,false則表示可讀寫,如@Transactional(re

    2、使用SPRING的執行緒池ThreadPoolTaskExecutor實現JAVA併發

    new Thread的弊端如下:a. 每次new Thread新建物件效能差。b. 執行緒缺乏統一管理,可能無限制新建執行緒,相互之間競爭,及可能佔用過多系統資源導致宕機或oom。c. 缺乏更多功能,如定時執行、定期執行、執行緒中斷。相比new Thread,Java提供的四種執行緒池的好處在於:a

    JavaWeb-Spring註解大全與詳解

    可以通過該型別 status 物件顯式結束表單的處理,這相當於觸發 session 清除其中的通過@SessionAttributes 定義的屬性  請求處理方法返回值的可選型別 • void 此時邏輯檢視名由請求處理方法對應的 URL 確定,如以下的方法: @RequestMapping("/welc

    實戰 :Spring MVC + 註解 +SqlServer 框架搭建及詳解

    先說一下Spring3 MVC的優點: spring MVC 屬於輕量級框架 1、Spring3 MVC的學習難度小於Struts2,Struts2用不上的多餘功能太多。呵呵,當然這不是決定因素。 2、Spring3 MVC很容易就可以寫出效能優秀的程式,Str

    使用SPRING的執行緒池ThreadPoolTaskExecutor實現JAVA併發

    使用SPRING中的執行緒池ThreadPoolTaskExecutor實現併發。 一:不需要返回值的情況  1,初始化執行緒池 Java程式碼   ThreadPoolTaskExecutor poolTaskExecutor = new ThreadPool

    spring註解@component解釋

        在持久層、業務層和控制層分別採用 @Repository、@Service 和 @Controller 對分層中的類進行註釋,而用 @Component 對那些比較中立的類進行註釋。這裡就是說把這個類交給Spring管理,重新起個名字叫userManager,由於不好