Spring IOC 常用註解

註解實現Bean配置主要用來進行如依賴注入、生命週期回調方法定義等,不能消除XML文件中的Bean元數據定義,且基於XML配置中的依賴注入的數據將覆蓋基於註解配置中的依賴注入的數據
註冊註解處理器

 方式一:bean

[html] view plaincopy
  1. <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>  

 方式二: 命名空間<context:annotation-config />

<context:annotationconfig /> 將隱式地向spring 容器註冊AutowiredAnnotationBeanPostProcessor 、CommonAnnotationBeanPostProcessor 、 PersistenceAnnotationBeanPostProcessor 以及RequiredAnnotationBeanPostProcessor 這4 個BeanPostProcessor 。

 方式三: 命名空間<context:component-scan />

如果要使註解工作,則必須配置component-scan ,實際上不需要再配置annotation-config。

[html] view plaincopy
  1. <context:component-scan base-package="com.spring.ioc5">  
  2.         <!-- annotation 通過註解來過濾          org.example.SomeAnnotation    
  3.              assignable 通過指定名稱過濾        org.example.SomeClass  
  4.              regex      通過正則表達式過濾      org\.example\.Default.*  
  5.              aspectj    通過aspectj表達式過濾  org.example..*Service+  
  6.          -->  
  7.         <context:include-filter type="regex" expression="com.spring.ioc5.*"/>  
  8.         <context:exclude-filter type="annotation" expression="org.springframework.beans.factory.annotation.Autowired"/>  
  9. </context:component-scan>  

 

• Spring 支持以下4 種類型的過濾方式:

     • 註解 org.example.SomeAnnotation 將所有使用SomeAnnotation 註解的類過濾出來

     • 類名指定 org.example.SomeClass 過濾指定的類

     • 正則表達式 com.kedacom.spring.annotation.web..* 通過正則表達式過濾一些類

     • AspectJ 表達式 org.example..*Service+ 通過AspectJ 表達式過濾一些類


Spring3的基於註解實現Bean依賴注入支持如下三種註解:

  • Spring自帶依賴注入註解: Spring自帶的一套依賴注入註解;
  • JSR-250註解:Java平臺的公共註解,是Java EE 5規範之一,在JDK6中默認包含這些註解,從Spring2.5開始支持。
  • JSR-330註解:Java 依賴注入標準,Java EE 6規範之一,可能在加入到未來JDK版本,從Spring3開始支持;
  • JPA註解:用於注入持久化上下文和屍體管理器。


@Required

         • 例如 

[java] view plaincopy
  1. @required                
  2. public  setName(String name){}  
              @ required 負責檢查一個bean在初始化時其聲明的 set方法是否被執行, 當某個被標註了 @Required 的 Setter 方法沒有被調用,則 Spring 在解析的時候會拋出異常,以提醒開發者對相應屬性進行設置。 @Required 註解只能標註在 Setter 方法之上。因爲依賴注入的本質是檢查 Setter 方法是否被調用了,而不是真的去檢查屬性是否賦值了以及賦了什麼樣的值。如果將該註解標註在非 setXxxx() 類型的方法則被忽略。



@Autowired 採用byType的方式 


[java] view plaincopy
  1. @Autowired  
  2. private ISoftPMService softPMService;  
[java] view plaincopy
  1. @Autowired(required=false)  
  2.     構造器、字段、方法  

       @Autowired 根據bean 類型從spring 上線文中進行查找,註冊類型必須唯一,否則報異常。與@Resource 的區別在於,@Resource 允許通過bean 名稱或bean 類型兩種方式進行查找@Autowired(required=false) 表示,如果spring 上下文中沒有找到該類型的bean 時, 纔會使用new SoftPMServiceImpl();
       @Autowired 標註作用於 Map 類型時,如果 Map 的 key 爲 String 類型,則 Spring 會將容器中所有類型符合 Map 的 value 對應的類型的 Bean 增加進來,用 Bean 的 id 或 name 作爲 Map 的 key。
       @Autowired 還有一個作用就是,如果將其標註在 BeanFactory 類型、ApplicationContext 類型、ResourceLoader 類型、ApplicationEventPublisher 類型、MessageSource 類型上,那麼 Spring 會自動注入這些實現類的實例,不需要額外的操作。


@Qualifier 和@AutoWired聯合使用,自動裝配的策略就變成byName

  使用@Autowired 時,如果找到多個同一類型的bean,則會拋異常,此時可以使用 @Qualifier("beanName"),明確指定bean的名稱進行注入,此時與 @Resource指定name屬性作用相同。

[java] view plaincopy
  1. @Qualifier(value = "限定標識符")     
  2. 字段、方法、參數    

(1)根據基於XML配置中的<qualifier>標籤指定的名字進行注入,使用如下方式指定名稱 
[java] view plaincopy
  1. <qualifier  type="org.springframework.beans.factory.annotation.Qualifier"  value="限定標識符"/>    
其中type屬性可選,指定類型,默認就是Qualifier註解類,name就是給Bean候選者指定限定標識符,一個Bean定義中只允許指定類型不同的<qualifier>,如果有多個相同type後面指定的將覆蓋前面的。
[java] view plaincopy
  1. @Autowired    
  2.    //根據<qualifier>標籤指定Bean限定標識符    
  3.    public void initDataSource(@Qualifier("mysqlDataSource") DataSource dataSource) {    
  4.        this.dataSource = dataSource;    
  5.    }    
使用@Qualifier("mysqlDataSource")來指定候選Bean的限定標識符,我們需要在配置文件中使用<qualifier>標籤來指定候選Bean的限定標識符“mysqlDataSource”:
  1. <bean id="mysqlDataSourceBean" class="org.springframework.jdbc.datasource.DriverManagerDataSource">   
  2.      <qualifier value="mysqlDataSource"/>   
  3. </bean>  

(2)缺省的根據Bean名字注入:最基本方式,是在Bean上沒有指定<qualifier>標籤時一種容錯機制,即缺省情況下使用Bean標識符注入,但如果你指定了<qualifier>標籤將不會發生容錯。
  1.     @Autowired  
  2.     @Qualifier(value = "mysqlDataSource2"//指定Bean限定標識符   
  3.     //@Qualifier(value = "mysqlDataSourceBean")   
  4.     //是錯誤的注入,不會發生回退容錯,因爲你指定了<qualifier>   
  5.     public void initDataSource(DataSource dataSource) {   
  6.         this.dataSource = dataSource;   
  7.     }   

(3)擴展@Qualifier限定描述符註解:對@Qualifier的擴展來提供細粒度選擇候選者;
如果我們有兩個數據源,分別爲Mysql和Oracle,因此注入兩者相關資源時就牽扯到數據庫相關,如在DAO層注入SessionFactory時,當然可以採用前邊介紹的方式,但爲了簡單和直觀我們希望採用自定義註解方式。
1. 擴展@Qualifier限定描述符註解來分別表示Mysql和Oracle數據源
  1. /** 表示注入Mysql相關 */  
  2. @Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})   
  3. @Retention(RetentionPolicy.RUNTIME)   
  4. @Qualifier  
  5. public @interface Mysql {   
  6. }  

  1. /** 表示注入Oracle相關 */  
  2. @Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})   
  3. @Retention(RetentionPolicy.RUNTIME)   
  4. @Qualifier  
  5. public @interface Oracle {   
  6. }  

  1. @Autowired  
  2.     public void initDataSource(@Mysql DataSource mysqlDataSource, @Oracle DataSource oracleDataSource) {   
  3.         this.mysqlDataSource = mysqlDataSource;   
  4.         this.oracleDataSource = oracleDataSource;   
  5.     }   

  1. <bean id="mysqlDataSourceBean" class="org.springframework.jdbc.datasource.DriverManagerDataSource">   
  2.      <qualifier value="mysqlDataSource"/>   
  3.      <qualifier type="cn.javass.spring.chapter12.qualifier.Mysql"/>   
  4. </bean>   
  5. <bean id="oracleDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">   
  6.       <qualifier type="cn.javass.spring.chapter12.qualifier.Oracle"/>   
  7. </bean>
     
  1.  Assert.assertEquals(ctx.getBean("mysqlDataSourceBean"), testBean33.getMysqlDataSoruce());  
  2.  Assert.assertEquals(ctx.getBean("oracleDataSource"), testBean33.getOracleDataSoruce());  
測試通過

2.擴展參數的註解
  1. package cn.javass.spring.chapter12.qualifier;   
  2. public enum DataBase {   
  3.     ORACLE, MYSQL;   
  4. }  

  1. @Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})   
  2. @Retention(RetentionPolicy.RUNTIME)   
  3. @Qualifier  
  4. public @interface DataSourceType {   
  5.     String ip();      //指定ip,用於多數據源情況   
  6.     DataBase database();//指定數據庫類型   
  7. }  

  1. @Autowired  
  2.     public void initDataSource(   
  3.             @DataSourceType(ip="localhost", database=DataBase.MYSQL)   
  4.             DataSource mysqlDataSource,   
  5.             @DataSourceType(ip="localhost", database=DataBase.ORACLE)   
  6.             DataSource oracleDataSource) {   
  7.         this.mysqlDataSource = mysqlDataSource;   
  8.         this.oracleDataSource = oracleDataSource;   
  9.     }   

  1. <bean id="mysqlDataSourceBean" class="org.springframework.jdbc.datasource.DriverManagerDataSource">   
  2.     <qualifier value="mysqlDataSource"/>   
  3.     <qualifier type="cn.javass.spring.chapter12.qualifier.Mysql"/>   
  4.     <qualifier type="cn.javass.spring.chapter12.qualifier.DataSourceType">   
  5.         <attribute key="ip" value="localhost"/>   
  6.         <attribute key="database" value="MYSQL"/>   
  7.     </qualifier>   
  8. </bean>   
  9. <bean id="oracleDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">   
  10.     <qualifier type="cn.javass.spring.chapter12.qualifier.Oracle"/>   
  11.     <qualifier type="cn.javass.spring.chapter12.qualifier.DataSourceType">   
  12.         <attribute key="ip" value="localhost"/>   
  13.         <attribute key="database" value="ORACLE"/>   
  14.     </qualifier>   
  15. </bean>  

  1. Assert.assertEquals(ctx.getBean("mysqlDataSourceBean"), testBean34.getMysqlDataSource());   
  2. Assert.assertEquals(ctx.getBean("oracleDataSource"), testBean34.getOracleDataSoruce());   
測試通過

3. 自定義註解限定描述符:完全不使用@Qualifier,而是自己定義一個獨立的限定註解;
  1. @Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})   
  2. @Retention(RetentionPolicy.RUNTIME)   
  3. public @interface CustomQualifier {   
  4.     String value();   
  5. }  

  1. @Autowired  
  2.     public TestBean35(@CustomQualifier("oracleDataSource") DataSource dataSource) {   
  3.         this.dataSoruce = dataSource;   
  4.     } 
在Spring配置文件中註冊CustomQualifier自定義註解限定描述符,只有註冊了Spring才能識別:
  1. <bean id="customAutowireConfigurer" class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">   
  2.     <property name="customQualifierTypes">   
  3.         <set>   
  4.             <value>cn.javass.spring.chapter12.qualifier.CustomQualifier</value>   
  5.         </set>   
  6.    </property>   
  7. </bean>  



@Value

用於注入SpEL表達式,可以放置在字段方法或參數上

[java] view plaincopy
  1. @Value(value = "SpEL表達式")     
  2. 字段、方法、參數  
1、可以在類字段上使用該註解:
  1. @Value(value = "#{message}")   
  2. private String message;  


2、可以放置在帶@Autowired註解的方法的參數上
  1. @Autowired  
  2. public void initMessage(@Value(value = "#{message}#{message}") String message) {   
  3.     this.message = message;   
  4. }  


3、還可以放置在帶@Autowired註解的構造器的參數上:
  1. @Autowired  
  2. private TestBean43(@Value(value = "#{message}#{message}") String message) {   
  3.     this.message = message;   
  4. }  



@Lazy
定義Bean將延遲初始化
  1. @Component("component")   
  2. @Lazy(true)   
  3. public class TestCompoment {   
  4. ……   
  5. } 

@DependsOn
定義Bean初始化及銷燬時的順序
  1. @Component("component")   
  2. @DependsOn({"managedBean"})   
  3. public class TestCompoment {   
  4. ……   
  5. }  

@Scope
定義Bean作用域,默認單例
  1. @Component("component")   
  2. @Scope("singleton")   
  3. public class TestCompoment {   
  4. ……   

@Primary
自動裝配時當出現多個Bean候選者時,被註解爲@Primary的Bean將作爲首選者,否則將拋出異常
  1. @Component("component")   
  2. @Primary  
  3. public class TestCompoment {   
  4. ……   

@Configuration
註解需要作爲配置的類,表示該類將定義Bean配置元數據,
@Configuration註解的類本身也是一個Bean,因爲@Configuration被@Component註解了,因此@Configuration註解可以指定value屬性值,如“ctxConfig”就是該Bean的名字,如使用“ctx.getBean("ctxConfig")”將返回該Bean。
[java] view plaincopy
  1. <span style="font-size:10px;font-weight: normal;">@Configuration("ctxConfig")     
  2. public class ApplicationContextConfig {     
  3.     //定義Bean配置元數據     
  4. }  </span>  

@Bean
註解配置類中的相應方法,則該方法名默認就是Bean名,該方法返回值就是Bean對象,並定義了Spring IoC容器如何實例化、自動裝配、初始化Bean邏輯
[java] view plaincopy
  1. <span style="font-weight: normal;"><span style="font-size:10px;">@Bean(name={},     
  2.       autowire=Autowire.NO,     
  3.       initMethod="",     
  4.       destroyMethod="")  </span></span>  
  • name:指定Bean的名字,可有多個,第一個作爲Id,其他作爲別名;
  • autowire:自動裝配,默認no表示不自動裝配該Bean,另外還有Autowire.BY_NAME表示根據名字自動裝配,Autowire.BY_TYPE表示根據類型自動裝配;
  • initMethod和destroyMethod:指定Bean的初始化和銷燬方法。

@Import
類似於基於XML配置中的<import/>,基於Java的配置方式提供了@Import來組合模塊化的配置類

[java] view plaincopy
  1. <span style="font-size:10px;font-weight: normal;">@Configuration("ctxConfig2")     
  2. @Import({ApplicationContextConfig.class})     
  3. public class ApplicationContextConfig2 {     
  4.     @Bean(name = {"message2"})     
  5.     public String message() {     
  6.         return "hello";     
  7.     }     
  8. }  </span>  






JSR-250註解@Resource 

自動裝配,默認根據類型裝配,如果指定name屬性將根據名字裝配,可以使用如下方式來指定

[java] view plaincopy
  1. <span style="white-space:pre">  </span>@Resource(name = "message")     
  2.    <span style="white-space:pre">   </span>private String message;    
  • @Resource註解應該只用於setter方法注入,不能提供如@Autowired多參數方法注入;
  • @Resource在沒有指定name屬性的情況下首先將根據setter方法對於的字段名查找資源,如果找不到再根據類型查找;
  • @Resource首先將從JNDI環境中查找資源,如果沒找到默認再到Spring容器中查找,因此如果JNDI環境中有和Spring容器同名的資源時需要注意。
@PostConstruct和PreDestroy:通過註解指定初始化和銷燬方法定義;
類似於通過<bean>標籤的init-method和destroy-method屬性指定的初始化和銷燬方法,但具有更高優先級,即註解方式的初始化和銷燬方法將先執行。
• @PostConstruct在方法上加上註解@PostConstruct ,這個方法就會在Bean 初始化之後被Spring 容器執(注:Bean 初始化包括,實例化Bean ,並裝配Bean 的屬性(依賴注入))。
• @PreDestroy             在方法上加上註解@PreDestroy ,這個方法就會在Bean 被銷燬前被Spring 容器執行。



JSR-330註解

@Inject:等價於默認的@Autowired,只是沒有required屬性;

@Named:指定Bean名字,對應於Spring自帶@Qualifier中的缺省的根據Bean名字注入情況;

@Qualifier:只對應於Spring自帶@Qualifier中的擴展@Qualifier限定描述符註解,即只能擴展使用,沒有value屬性。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章