註冊註解處理器
• 方式一:bean
• 方式二: 命名空間<context:annotation-config />
<context:annotationconfig /> 將隱式地向spring 容器註冊AutowiredAnnotationBeanPostProcessor 、CommonAnnotationBeanPostProcessor 、 PersistenceAnnotationBeanPostProcessor 以及RequiredAnnotationBeanPostProcessor 這4 個BeanPostProcessor 。
• 方式三: 命名空間<context:component-scan />
如果要使註解工作,則必須配置component-scan ,實際上不需要再配置annotation-config。
• 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
• 例如
@Autowired 採用byType的方式
@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屬性作用相同。
(1)根據基於XML配置中的<qualifier>標籤指定的名字進行注入,使用如下方式指定名稱
其中type屬性可選,指定類型,默認就是Qualifier註解類,name就是給Bean候選者指定限定標識符,一個Bean定義中只允許指定類型不同的<qualifier>,如果有多個相同type後面指定的將覆蓋前面的。
使用@Qualifier("mysqlDataSource")來指定候選Bean的限定標識符,我們需要在配置文件中使用<qualifier>標籤來指定候選Bean的限定標識符“mysqlDataSource”:
- <bean id="mysqlDataSourceBean" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
- <qualifier value="mysqlDataSource"/>
- </bean>
(2)缺省的根據Bean名字注入:最基本方式,是在Bean上沒有指定<qualifier>標籤時一種容錯機制,即缺省情況下使用Bean標識符注入,但如果你指定了<qualifier>標籤將不會發生容錯。
- @Autowired
- @Qualifier(value = "mysqlDataSource2") //指定Bean限定標識符
- //@Qualifier(value = "mysqlDataSourceBean")
- //是錯誤的注入,不會發生回退容錯,因爲你指定了<qualifier>
- public void initDataSource(DataSource dataSource) {
- this.dataSource = dataSource;
- }
(3)擴展@Qualifier限定描述符註解:對@Qualifier的擴展來提供細粒度選擇候選者;
如果我們有兩個數據源,分別爲Mysql和Oracle,因此注入兩者相關資源時就牽扯到數據庫相關,如在DAO層注入SessionFactory時,當然可以採用前邊介紹的方式,但爲了簡單和直觀我們希望採用自定義註解方式。
1. 擴展@Qualifier限定描述符註解來分別表示Mysql和Oracle數據源
- /** 表示注入Mysql相關 */
- @Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
- @Retention(RetentionPolicy.RUNTIME)
- @Qualifier
- public @interface Mysql {
-
}
- /** 表示注入Oracle相關 */
- @Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
- @Retention(RetentionPolicy.RUNTIME)
- @Qualifier
- public @interface Oracle {
-
}
- @Autowired
- public void initDataSource(@Mysql DataSource mysqlDataSource, @Oracle DataSource oracleDataSource) {
- this.mysqlDataSource = mysqlDataSource;
- this.oracleDataSource = oracleDataSource;
-
}
- <bean id="mysqlDataSourceBean" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
- <qualifier value="mysqlDataSource"/>
- <qualifier type="cn.javass.spring.chapter12.qualifier.Mysql"/>
- </bean>
- <bean id="oracleDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
- <qualifier type="cn.javass.spring.chapter12.qualifier.Oracle"/>
-
</bean>
- Assert.assertEquals(ctx.getBean("mysqlDataSourceBean"), testBean33.getMysqlDataSoruce());
- Assert.assertEquals(ctx.getBean("oracleDataSource"), testBean33.getOracleDataSoruce());
2.擴展參數的註解
- package cn.javass.spring.chapter12.qualifier;
- public enum DataBase {
- ORACLE, MYSQL;
-
}
- @Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
- @Retention(RetentionPolicy.RUNTIME)
- @Qualifier
- public @interface DataSourceType {
- String ip(); //指定ip,用於多數據源情況
- DataBase database();//指定數據庫類型
-
}
- @Autowired
- public void initDataSource(
- @DataSourceType(ip="localhost", database=DataBase.MYSQL)
- DataSource mysqlDataSource,
- @DataSourceType(ip="localhost", database=DataBase.ORACLE)
- DataSource oracleDataSource) {
- this.mysqlDataSource = mysqlDataSource;
- this.oracleDataSource = oracleDataSource;
-
}
- <bean id="mysqlDataSourceBean" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
- <qualifier value="mysqlDataSource"/>
- <qualifier type="cn.javass.spring.chapter12.qualifier.Mysql"/>
- <qualifier type="cn.javass.spring.chapter12.qualifier.DataSourceType">
- <attribute key="ip" value="localhost"/>
- <attribute key="database" value="MYSQL"/>
- </qualifier>
- </bean>
- <bean id="oracleDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
- <qualifier type="cn.javass.spring.chapter12.qualifier.Oracle"/>
- <qualifier type="cn.javass.spring.chapter12.qualifier.DataSourceType">
- <attribute key="ip" value="localhost"/>
- <attribute key="database" value="ORACLE"/>
- </qualifier>
-
</bean>
- Assert.assertEquals(ctx.getBean("mysqlDataSourceBean"), testBean34.getMysqlDataSource());
- Assert.assertEquals(ctx.getBean("oracleDataSource"), testBean34.getOracleDataSoruce());
3. 自定義註解限定描述符:完全不使用@Qualifier,而是自己定義一個獨立的限定註解;
- @Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
- @Retention(RetentionPolicy.RUNTIME)
- public @interface CustomQualifier {
- String value();
-
}
- @Autowired
- public TestBean35(@CustomQualifier("oracleDataSource") DataSource dataSource) {
- this.dataSoruce = dataSource;
- }
- <bean id="customAutowireConfigurer" class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
- <property name="customQualifierTypes">
- <set>
- <value>cn.javass.spring.chapter12.qualifier.CustomQualifier</value>
- </set>
- </property>
- </bean>
@Value
用於注入SpEL表達式,可以放置在字段方法或參數上
- @Value(value = "#{message}")
- private String message;
2、可以放置在帶@Autowired註解的方法的參數上
- @Autowired
- public void initMessage(@Value(value = "#{message}#{message}") String message) {
- this.message = message;
- }
3、還可以放置在帶@Autowired註解的構造器的參數上:
- @Autowired
- private TestBean43(@Value(value = "#{message}#{message}") String message) {
- this.message = message;
- }
@Lazy
定義Bean將延遲初始化
-
@Component("component")
-
@Lazy(true)
-
public class TestCompoment {
-
……
-
}
@DependsOn
定義Bean初始化及銷燬時的順序
-
@Component("component")
-
@DependsOn({"managedBean"})
-
public class TestCompoment {
-
……
-
}
@Scope
定義Bean作用域,默認單例
-
@Component("component")
-
@Scope("singleton")
-
public class TestCompoment {
-
……
-
}
@Primary
自動裝配時當出現多個Bean候選者時,被註解爲@Primary的Bean將作爲首選者,否則將拋出異常
-
@Component("component")
-
@Primary
-
public class TestCompoment {
-
……
-
}
@Configuration
註解需要作爲配置的類,表示該類將定義Bean配置元數據,@Configuration註解的類本身也是一個Bean,因爲@Configuration被@Component註解了,因此@Configuration註解可以指定value屬性值,如“ctxConfig”就是該Bean的名字,如使用“ctx.getBean("ctxConfig")”將返回該Bean。
@Bean
註解配置類中的相應方法,則該方法名默認就是Bean名,該方法返回值就是Bean對象,並定義了Spring IoC容器如何實例化、自動裝配、初始化Bean邏輯
- name:指定Bean的名字,可有多個,第一個作爲Id,其他作爲別名;
- autowire:自動裝配,默認no表示不自動裝配該Bean,另外還有Autowire.BY_NAME表示根據名字自動裝配,Autowire.BY_TYPE表示根據類型自動裝配;
- initMethod和destroyMethod:指定Bean的初始化和銷燬方法。
@Import
類似於基於XML配置中的<import/>,基於Java的配置方式提供了@Import來組合模塊化的配置類
JSR-250註解@Resource
自動裝配,默認根據類型裝配,如果指定name屬性將根據名字裝配,可以使用如下方式來指定
- @Resource註解應該只用於setter方法注入,不能提供如@Autowired多參數方法注入;
- @Resource在沒有指定name屬性的情況下首先將根據setter方法對於的字段名查找資源,如果找不到再根據類型查找;
- @Resource首先將從JNDI環境中查找資源,如果沒找到默認再到Spring容器中查找,因此如果JNDI環境中有和Spring容器同名的資源時需要注意。
類似於通過<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屬性。