spring使用註解注入bean理解
註解實現Bean依賴注入
1.概述
註解實現Bean配置主要用來進行如依賴注入、生命週期回撥方法定義等,不能消除XML檔案中的Bean後設資料定義,且基於XML配置中的依賴注入的資料將覆蓋基於註解配置中的依賴注入的資料。
Spring3的基於註解實現Bean依賴注入支援如下三種註解:
- Spring自帶依賴注入註解: Spring自帶的一套依賴注入註解;
- JSR-250註解:Java平臺的公共註解,是Java EE 5規範之一,在JDK6中預設包含這些註解,從Spring2.5開始支援。
- JSR-330註解:Java 依賴注入標準,Java EE 6規範之一,可能在加入到未來JDK版本,從Spring3開始支援;
- JPA註解:用於注入持久化上下文和屍體管理器。
這三種型別的註解在Spring3中都支援,類似於註解事務支援,想要使用這些註解需要在Spring容器中開啟註解驅動支援,即使用如下配置方式開啟:
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xsi:schemaLocation=" http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.0.xsd">
- <context:annotation-config/>
- </beans>
這樣就能使用註解驅動依賴注入了,該配置檔案位於“resources/ chapter12/dependecyInjectWithAnnotation.xml”。
2. Spring自帶依賴注入註解
一、@Required:依賴檢查;
對應於基於XML配置中的依賴檢查,但XML配置的依賴檢查將檢查所有setter方法,詳見【3.3.4 依賴檢查】;
基於@Required的依賴檢查表示註解的setter方法必須,即必須通過在XML配置中配置setter注入,如果沒有配置在容器啟動時會丟擲異常從而保證在執行時不會遇到空指標異常,@Required只能放置在setter方法上,且通過XML配置的setter注入,可以使用如下方式來指定:
- @Requried
- setter方法
1、準備測試Bean
- package cn.javass.spring.chapter12;
- public class TestBean {
- private String message;
- @Required
- public void setMessage(String message) {
- this.message = message;
- }
- public String getMessage() {
- return message;
- }
- }
2、在Spring配置檔案(chapter12/dependecyInjectWithAnnotation.xml)新增如下Bean配置:
- <bean id="testBean" class="cn.javass.spring.chapter12.TestBean">
- <property name="message" ref="message"/>
- </bean>
- <bean id="message" class="java.lang.String">
- <constructor-arg index="0" value="hello"/>
- </bean>
3、測試類和測試方法如下:
- package cn.javass.spring.chapter12;
- //省略import
- public class DependencyInjectWithAnnotationTest {
- private static String configLocation = "classpath:chapter12/dependecyInjectWithAnnotation.xml";
- private static ApplicationContext ctx = new ClassPathXmlApplicationContext("configLocation");
- //1、Spring自帶依賴注入註解
- @Test
- public void testRequiredForXmlSetterInject() {
- TestBean testBean = ctx.getBean("testBean", TestBean.class);
- Assert.assertEquals("hello", testBean.getMessage());
- }
- }
在XML配置檔案中必須指定setter注入,否則在Spring容器啟動時將丟擲如下異常:
- org.springframework.beans.factory.BeanCreationException:
- Error creating bean with name 'testBean' defined in class path resource [chapter12/dependecyInjectWithAnnotation.xml]: Initialization of bean failed;
- nested exception is org.springframework.beans.factory.BeanInitializationException: Property 'message' is required for bean 'testBean'
二、@Autowired:自動裝配
自動裝配,用於替代基於XML配置的自動裝配,詳見【3.3.3 自動裝配】。
基於@Autowired的自動裝配,預設是根據型別注入,可以用於構造器、欄位、方法注入,使用方式如下:
- @Autowired(required=true)
- 構造器、欄位、方法
@Autowired預設是根據引數型別進行自動裝配,且必須有一個Bean候選者注入,如果允許出現0個Bean候選者需要設定屬性“required=false”,“required”屬性含義和@Required一樣,只是@Required只適用於基於XML配置的setter注入方式。
(1)、構造器注入:通過將@Autowired註解放在構造器上來完成構造器注入,預設構造器引數通過型別自動裝配,如下所示:
1、準備測試Bean,在構造器上新增@AutoWired註解:
- package cn.javass.spring.chapter12;
- import org.springframework.beans.factory.annotation.Autowired;
- public class TestBean11 {
- private String message;
- @Autowired //構造器注入
- private TestBean11(String message) {
- this.message = message;
- }
- //省略message的getter和setter
- }
2、在Spring配置檔案(chapter12/dependecyInjectWithAnnotation.xml)新增如下Bean配置:
- <bean id="testBean11" class="cn.javass.spring.chapter12.TestBean11"/>
3、測試類如下:
- @Test
- public void testAutowiredForConstructor() {
- TestBean11 testBean11 = ctx.getBean("testBean11", TestBean11.class);
- Assert.assertEquals("hello", testBean11.getMessage());
- }
在Spring配置檔案中沒有對“testBean11”進行構造器注入和setter注入配置,而是通過在構造器上新增@ Autowired來完成根據引數型別完成構造器注入。
(2)、欄位注入:通過將@Autowired註解放在構造器上來完成欄位注入。
1、準備測試Bean,在欄位上新增@AutoWired註解:
- package cn.javass.spring.chapter12;
- import org.springframework.beans.factory.annotation.Autowired;
- public class TestBean12 {
- @Autowired //欄位注入
- private String message;
- //省略getter和setter
- }
2、在Spring配置檔案(chapter12/dependecyInjectWithAnnotation.xml)新增如下Bean配置:
- <bean id="testBean12" class="cn.javass.spring.chapter12.TestBean12"/>
3、測試方法如下:
- @Test
- public void testAutowiredForField() {
- TestBean12 testBean12 = ctx.getBean("testBean12", TestBean12.class);
- Assert.assertEquals("hello", testBean12.getMessage());
- }
欄位注入在基於XML配置中無相應概念,欄位注入不支援靜態型別欄位的注入。
(3)、方法引數注入:通過將@Autowired註解放在方法上來完成方法引數注入。
1、準備測試Bean,在方法上新增@AutoWired註解:
- package cn.javass.spring.chapter12;
- import org.springframework.beans.factory.annotation.Autowired;
- public class TestBean13 {
- private String message;
- @Autowired //setter方法注入
- public void setMessage(String message) {
- this.message = message;
- }
- public String getMessage() {
- return message;
- }
- }
- package cn.javass.spring.chapter12;
- //省略import
- public class TestBean14 {
- private String message;
- private List<String> list;
- @Autowired(required = true) //任意一個或多個引數方法注入
- private void initMessage(String message, ArrayList<String> list) {
- this.message = message;
- this.list = list;
- }
- //省略getter和setter
- }
2、在Spring配置檔案(chapter12/dependecyInjectWithAnnotation.xml)新增如下Bean配置:
- <bean id="testBean13" class="cn.javass.spring.chapter12.TestBean13"/>
- <bean id="testBean14" class="cn.javass.spring.chapter12.TestBean14"/>
- <bean id="list" class="java.util.ArrayList">
- <constructor-arg index="0">
- <list>
- <ref bean="message"/>
- <ref bean="message"/>
- </list>
- </constructor-arg>
- </bean>
3、測試方法如下:
- @Test
- public void testAutowiredForMethod() {
- TestBean13 testBean13 = ctx.getBean("testBean13", TestBean13.class);
- Assert.assertEquals("hello", testBean13.getMessage());
- TestBean14 testBean14 = ctx.getBean("testBean14", TestBean14.class);
- Assert.assertEquals("hello", testBean14.getMessage());
- Assert.assertEquals(ctx.getBean("list", List.class), testBean14.getList());
- }
方法引數注入除了支援setter方法注入,還支援1個或多個引數的普通方法注入,在基於XML配置中不支援1個或多個引數的普通方法注入,方法注入不支援靜態型別方法的注入。
注意“initMessage(String message, ArrayList<String> list)”方法簽名中為什麼使用ArrayList而不是List呢?具體參考【3.3.3 自動裝配】一節中的集合型別注入區別。
三、@Value:注入SpEL表示式;
用於注入SpEL表示式,可以放置在欄位方法或引數上,使用方式如下:
- @Value(value = "SpEL表示式")
- 欄位、方法、引數
1、可以在類欄位上使用該註解:
- @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;
- }
具體測試詳見DependencyInjectWithAnnotationTest 類的testValueInject測試方法。
四、@Qualifier:限定描述符,用於細粒度選擇候選者;
@Autowired預設是根據型別進行注入的,因此如果有多個型別一樣的Bean候選者,則需要限定其中一個候選者,否則將丟擲異常,詳見【3.3.3 自動裝配】中的根據型別進行注入;
@Qualifier限定描述符除了能根據名字進行注入,但能進行更細粒度的控制如何選擇候選者,具體使用方式如下:
- @Qualifier(value = "限定識別符號")
- 欄位、方法、引數
(1)、根據基於XML配置中的<qualifier>標籤指定的名字進行注入,使用如下方式指定名稱:
- <qualifier type="org.springframework.beans.factory.annotation.Qualifier" value="限定識別符號"/>
其中type屬性可選,指定型別,預設就是Qualifier註解類,name就是給Bean候選者指定限定識別符號,一個Bean定義中只允許指定型別不同的<qualifier>,如果有多個相同type後面指定的將覆蓋前面的。
1、準備測試Bean:
- package cn.javass.spring.chapter12;
- import javax.sql.DataSource;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Qualifier;
- public class TestBean31 {
- private DataSource dataSource;
- @Autowired
- //根據<qualifier>標籤指定Bean限定識別符號
- public void initDataSource(@Qualifier("mysqlDataSource") DataSource dataSource) {
- this.dataSource = dataSource;
- }
- public DataSource getDataSource() {
- return dataSource;
- }
- }
2、在Spring配置檔案(chapter12/dependecyInjectWithAnnotation.xml)新增如下Bean配置:
- <bean id="testBean31" class="cn.javass.spring.chapter12.TestBean31"/>
我們使用@Qualifier("mysqlDataSource")來指定候選Bean的限定識別符號,我們需要在配置檔案中使用<qualifier>標籤來指定候選Bean的限定識別符號“mysqlDataSource”:
- <bean id="mysqlDataSourceBean" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
- <qualifier value="mysqlDataSource"/>
- </bean>
3、測試方法如下:
- @Test
- public void testQualifierInject1() {
- TestBean31 testBean31 = ctx.getBean("testBean31", TestBean31.class);
- try {
- //使用<qualifier>指定的識別符號只能被@Qualifier使用
- ctx.getBean("mysqlDataSource");
- Assert.fail();
- } catch (Exception e) {
- //找不到該Bean
- Assert.assertTrue(e instanceof NoSuchBeanDefinitionException);
- }
- Assert.assertEquals(ctx.getBean("mysqlDataSourceBean"), testBean31.getDataSource());
- }
從測試可以看出使用<qualifier>標籤指定的限定識別符號只能被@Qualifier使用,不能作為Bean的識別符號,如“ctx.getBean("mysqlDataSource")”是獲取不到Bean的。
(2)、預設的根據Bean名字注入:最基本方式,是在Bean上沒有指定<qualifier>標籤時一種容錯機制,即預設情況下使用Bean識別符號注入,但如果你指定了<qualifier>標籤將不會發生容錯。
1、準備測試Bean:
- package cn.javass.spring.chapter12;
- //省略import
- public class TestBean32 {
- private DataSource dataSource;
- @Autowired
- @Qualifier(value = "mysqlDataSource2") //指定Bean限定識別符號
- //@Qualifier(value = "mysqlDataSourceBean")
- //是錯誤的注入,不會發生回退容錯,因為你指定了<qualifier>
- public void initDataSource(DataSource dataSource) {
- this.dataSource = dataSource;
- }
- public DataSource getDataSource() {
- return dataSource;
- }
- }
2、在Spring配置檔案(chapter12/dependecyInjectWithAnnotation.xml)新增如下Bean配置:
- <bean id="testBean32" class="cn.javass.spring.chapter12.TestBean32"/>
- <bean id="oracleDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"/>
3、測試方法如下:
- @Test
- public void testQualifierInject2() {
- TestBean32 testBean32 = ctx.getBean("testBean32", TestBean32.class);
- Assert.assertEquals(ctx.getBean("oracleDataSource"), testBean32.getDataSource());
- }
預設情況下(沒指定<qualifier>標籤)@Qualifier的value屬性將匹配Bean 識別符號。
(3)、擴充套件@Qualifier限定描述符註解:對@Qualifier的擴充套件來提供細粒度選擇候選者;
具體使用方式就是自定義一個註解並使用@Qualifier註解其即可使用。
首先讓我們考慮這樣一個問題,如果我們有兩個資料來源,分別為Mysql和Oracle,因此注入兩者相關資源時就牽扯到資料庫相關,如在DAO層注入SessionFactory時,當然可以採用前邊介紹的方式,但為了簡單和直觀我們希望採用自定義註解方式。
1、擴充套件@Qualifier限定描述符註解來分別表示Mysql和Oracle資料來源
- package cn.javass.spring.chapter12.qualifier;
- import org.springframework.beans.factory.annotation.Qualifier;
- /** 表示注入Mysql相關 */
- @Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
- @Retention(RetentionPolicy.RUNTIME)
- @Qualifier
- public @interface Mysql {
- }
- package cn.javass.spring.chapter12.qualifier;
- import org.springframework.beans.factory.annotation.Qualifier;
- /** 表示注入Oracle相關 */
- @Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
- @Retention(RetentionPolicy.RUNTIME)
- @Qualifier
- public @interface Oracle {
- }
2、準備測試Bean:
- package cn.javass.spring.chapter12;
- //省略import
- public class TestBean33 {
- private DataSource mysqlDataSource;
- private DataSource oracleDataSource;
- @Autowired
- public void initDataSource(@Mysql DataSource mysqlDataSource, @Oracle DataSource oracleDataSource) {
- this.mysqlDataSource = mysqlDataSource;
- this.oracleDataSource = oracleDataSource;
- }
- public DataSource getMysqlDataSource() {
- return mysqlDataSource;
- }
- public DataSource getOracleDataSource() {
- return oracleDataSource;
- }
- }
3、在Spring配置檔案(chapter12/dependecyInjectWithAnnotation.xml)新增如下Bean配置:
- <bean id="testBean33" class="cn.javass.spring.chapter12.TestBean33"/>
4、在Spring修改定義的兩個資料來源:
- <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>
5、測試方法如下:
- @Test
- public void testQualifierInject3() {
- TestBean33 testBean33 = ctx.getBean("testBean33", TestBean33.class);
- Assert.assertEquals(ctx.getBean("mysqlDataSourceBean"), testBean33.getMysqlDataSoruce());
- Assert.assertEquals(ctx.getBean("oracleDataSource"), testBean33.getOracleDataSoruce());
- }
測試也通過了,說明我們擴充套件的@Qualifier限定描述符註解也能很好工作。
前邊演示了不帶屬性的註解,接下來演示一下帶引數的註解:
1、首先定義資料庫型別:
- package cn.javass.spring.chapter12.qualifier;
- public enum DataBase {
- ORACLE, MYSQL;
- }
2、其次擴充套件@Qualifier限定描述符註解
- package cn.javass.spring.chapter12.qualifier;
- //省略import
- @Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
- @Retention(RetentionPolicy.RUNTIME)
- @Qualifier
- public @interface DataSourceType {
- String ip(); //指定ip,用於多資料來源情況
- DataBase database();//指定資料庫型別
- }
3、準備測試Bean:
- package cn.javass.spring.chapter12;
- import javax.sql.DataSource;
- import org.springframework.beans.factory.annotation.Autowired;
- import cn.javass.spring.chapter12.qualifier.DataBase;
- import cn.javass.spring.chapter12.qualifier.DataSourceType;
- public class TestBean34 {
- private DataSource mysqlDataSource;
- private DataSource oracleDataSource;
- @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;
- }
- //省略getter方法
- }
4、在Spring配置檔案(chapter12/dependecyInjectWithAnnotation.xml)新增如下Bean配置:
- <bean id="testBean34" class="cn.javass.spring.chapter12.TestBean34"/>
5、在Spring修改定義的兩個資料來源:
- <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>
6、測試方法如下:
- @Test
- public void testQualifierInject3() {
- TestBean34 testBean34 = ctx.getBean("testBean34", TestBean34.class);
- Assert.assertEquals(ctx.getBean("mysqlDataSourceBean"), testBean34.getMysqlDataSource());
- Assert.assertEquals(ctx.getBean("oracleDataSource"), testBean34.getOracleDataSoruce());
- }
測試也通過了,說明我們擴充套件的@Qualifier限定描述符註解也能很好工作。
四、自定義註解限定描述符:完全不使用@Qualifier,而是自己定義一個獨立的限定註解;
1、首先使用如下方式定義一個自定義註解限定描述符:
- package cn.javass.spring.chapter12.qualifier;
- //省略import
- @Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
- @Retention(RetentionPolicy.RUNTIME)
- public @interface CustomQualifier {
- String value();
- }
2、準備測試Bean:
- package cn.javass.spring.chapter12;
- //省略import
- public class TestBean35 {
- private DataSource dataSoruce;
- @Autowired
- public TestBean35(@CustomQualifier("oracleDataSource") DataSource dataSource) {
- this.dataSoruce = dataSource;
- }
- public DataSource getDataSoruce() {
- return dataSoruce;
- }
- }
3、在Spring配置檔案(chapter12/dependecyInjectWithAnnotation.xml)新增如下Bean配置:
- <bean id="testBean35" class="cn.javass.spring.chapter12.TestBean35"/>
4、然後在Spring配置檔案中註冊CustomQualifier自定義註解限定描述符,只有註冊了Spring才能識別:
- <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>
5、測試方法如下:
- @Test
- public void testQualifierInject5() {
- TestBean35 testBean35 = ctx.getBean("testBean35", TestBean35.class);
- Assert.assertEquals(ctx.getBean("oracleDataSource"), testBean35.getDataSource());
- }
從測試中可看出,自定義的和Spring自帶的沒什麼區別,因此如果沒有足夠的理由請使用Spring自帶的Qualifier註解。
到此限定描述符介紹完畢,在此一定要注意以下幾點:
- 限定識別符號和Bean的描述符是不一樣的;
- 多個Bean定義中可以使用相同的限定識別符號;
- 對於集合、陣列、字典型別的限定描述符注入,將注入多個具有相同限定識別符號的Bean。
12.2.3 JSR-250註解
一、@Resource:自動裝配,預設根據型別裝配,如果指定name屬性將根據名字裝配,可以使用如下方式來指定:
- @Resource(name = "識別符號")
- 欄位或setter方法
1、準備測試Bean:
- package cn.javass.spring.chapter12;
- import javax.annotation.Resource;
- public class TestBean41 {
- @Resource(name = "message")
- private String message;
- //省略getter和setter
- }
2、在Spring配置檔案(chapter12/dependecyInjectWithAnnotation.xml)新增如下Bean配置:
- <bean id="testBean41" class="cn.javass.spring.chapter12.TestBean41"/>
3、測試方法如下:
- @Test
- public void testResourceInject1() {
- TestBean41 testBean41 = ctx.getBean("testBean41", TestBean41.class);
- Assert.assertEquals("hello", testBean41.getMessage());
- }
使用非常簡單,和@Autowired不同的是可以指定name來根據名字注入。
使用@Resource需要注意以下幾點:
- @Resource註解應該只用於setter方法注入,不能提供如@Autowired多引數方法注入;
- @Resource在沒有指定name屬性的情況下首先將根據setter方法對於的欄位名查詢資源,如果找不到再根據型別查詢;
- @Resource首先將從JNDI環境中查詢資源,如果沒找到預設再到Spring容器中查詢,因此如果JNDI環境中有和Spring容器同名的資源時需要注意。
二、@PostConstruct和PreDestroy:通過註解指定初始化和銷燬方法定義;
1、在測試類TestBean41中新增如下程式碼:
- @PostConstruct
- public void init() {
- System.out.println("==========init");
- }
- @PreDestroy
- public void destroy() {
- System.out.println("==========destroy");
- }
2、修改測試方法如下:
- @Test
- public void resourceInjectTest1() {
- ((ClassPathXmlApplicationContext) ctx).registerShutdownHook();
- TestBean41 testBean41 = ctx.getBean("testBean41", TestBean41.class);
- Assert.assertEquals("hello", testBean41.getMessage());
- }
類似於通過<bean>標籤的init-method和destroy-method屬性指定的初始化和銷燬方法,但具有更高優先順序,即註解方式的初始化和銷燬方法將先執行。
12.2.4 JSR-330註解
在測試之前需要準備JSR-330註解所需要的jar包,到spring-framework-3.0.5.RELEASE-dependencies.zip中拷貝如下jar包到類路徑:
com.springsource.javax.inject-1.0.0.jar |
一、@Inject:等價於預設的@Autowired,只是沒有required屬性;
二、@Named:指定Bean名字,對應於Spring自帶@Qualifier中的預設的根據Bean名字注入情況;
三、@Qualifier:只對應於Spring自帶@Qualifier中的擴充套件@Qualifier限定描述符註解,即只能擴充套件使用,沒有value屬性。
1、首先擴充套件@Qualifier限定描述符註解來表示Mysql資料來源
- package cn.javass.spring.chapter12.qualifier;
- //省略部分import
- import javax.inject.Qualifier;
- @Target({ElementType.FIELD, ElementType.PARAMETER})
- @Retention(RetentionPolicy.RUNTIME)
- @Qualifier
- public @interface JSR330Mysql {
- }
2、準備測試Bean:
- package cn.javass.spring.chapter12;
- import javax.inject.Inject;
- import javax.inject.Named;
- import javax.sql.DataSource;
- import cn.javass.spring.chapter12.qualifier.JSR330Mysql;
- public class TestBean51 {
- private DataSource mysqlDataSource;
- private DataSource oracleDataSource;
- @Inject
- public void initDataSoruce(
- @JSR330Mysql DataSource mysqlDataSource,
- @Named("oracleDataSource") DataSource oracleDataSource) {
- this.mysqlDataSource = mysqlDataSource;
- this.oracleDataSource = oracleDataSource;
- }
- //省略getter
- }
3、在Spring配置檔案(chapter12/dependecyInjectWithAnnotation.xml)新增如下Bean配置:
- <bean id="testBean51" class="cn.javass.spring.chapter12.TestBean51"/>
4、在Spring修改定義的mysqlDataSourceBean資料來源:
- <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>
- <qualifier type="cn.javass.spring.chapter12.qualifier.JSR330Mysql"/>
- </bean>
5、測試方法如下:
- @Test
- public void testInject() {
- TestBean51 testBean51 = ctx.getBean("testBean51", TestBean51.class);
- Assert.assertEquals(ctx.getBean("mysqlDataSourceBean"), testBean51.getMysqlDataSource());
- Assert.assertEquals(ctx.getBean("oracleDataSource"), testBean51.getOracleDataSource());
- }
測試也通過了,說明JSR-330註解也能很好工作。
從測試中可以看出JSR-330註解和Spring自帶註解依賴注入時主要有以下特點:
- Spring自帶的@Autowired的預設情況等價於JSR-330的@Inject註解;
- Spring自帶的@Qualifier的預設的根據Bean名字注入情況等價於JSR-330的@Named註解;
- Spring自帶的@Qualifier的擴充套件@Qualifier限定描述符註解情況等價於JSR-330的@Qualifier註解。
5 JPA註解
用於注入EntityManagerFactory和EntityManager。
1、準備測試Bean:
- package cn.javass.spring.chapter12;
- //省略import
- public class TestBean61 {
- @PersistenceContext(unitName = "entityManagerFactory")
- private EntityManager entityManager;
- @PersistenceUnit(unitName = "entityManagerFactory")
- private EntityManagerFactory entityManagerFactory;
- public EntityManager getEntityManager() {
- return entityManager;
- }
- public EntityManagerFactory getEntityManagerFactory() {
- return entityManagerFactory;
- }
- }
2、在Spring配置檔案(chapter12/dependecyInjectWithAnnotation.xml)新增如下Bean配置:
- <import resource="classpath:chapter7/applicationContext-resources.xml"/>
- <import resource="classpath:chapter8/applicationContext-jpa.xml"/>
- <bean id="testBean61" class="cn.javass.spring.chapter12.TestBean61"/>
此處需要引用第七章和八章的配置檔案,細節內容請參考七八兩章。
3、測試方法如下:
- @Test
- public void testJpaInject() {
- TestBean61 testBean61 = ctx.getBean("testBean61", TestBean61.class);
- Assert.assertNotNull(testBean61.getEntityManager());
- Assert.assertNotNull(testBean61.getEntityManagerFactory());
- }
測試也通過了,說明JPA註解也能很好工作。
JPA註解類似於@Resource註解同樣是先根據unitName屬性去JNDI環境中查詢,如果沒找到在到Spring容器中查詢。
6. 在spring 3.0中,可以通過使用@value,對一些如xxx.properties檔案中的檔案,進行鍵值對的注入,例子如下:
- < beans xmlns = “http://www.springframework.org/schema/beans”
- xmlns:xsi = “http://www.w3.org/2001/XMLSchema-instance”
- xsi:schemaLocation =“http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.0.xsd“ >
- < bean id = “propertyConfigurer” class = “org.springframework.beans.factory.config.PropertyPlaceholderConfigurer” >
- < property name = “locations” >
- < list >
- < value > classpath:test.properties </ value >
- </ list >
- </ property >
- </ bean >
建立test.properties
abc = 123
4。
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- @RequestMapping(“/ admin / images”)
- @Controller
- public class ImageAdminController {
- private String imageDir;
- @Value(“$ {abc}”)
- public void setImageDir(String val){
- 這個 .imageDir = val
- }
- }
有時候需要從屬性檔案中載入配置,以前的方式是這樣的:
- < bean id = “jdbcProperties” class = “org.springframework.beans.factory.config.PropertyPlaceholderConfigurer” >
- < property name = “locations” >
- < list >
- < value > classpath *:/ spring / jdbc.properties </ value >
- </ list >
- </ property >
- </ bean >
最近發現這樣也可以,程式碼更整潔:
- < context:property-placeholder location = “classpath:spring / jdbc.properties” />
在豆定義中依然可以通過“$ {}”這種方式來去值:
- < bean id = “dataSource” class = “org.apache.commons.dbcp.BasicDataSource” >
- < property name = “driverClassName” value = “$ {jdbc.driverClassName}” />
- < property name = “url” value = “$ {jdbc.url}” />
- < property name = “username” value = “$ {jdbc.username}” />
- < property name = “password” value = “$ {jdbc.password}” />
- < property name = “initialSize” value = “$ {jdbc.initialSize}” />
- < property name = “maxActive” value = “$ {jdbc.maxActive}” />
- < property name = “maxIdle” value = “$ {jdbc.maxIdle}” />
- < property name = “minIdle” value = “$ {jdbc.minIdle}” />
- </ bean >
<context:property-placeholder
... />
是與PropertyPlaceholderConfigurer相當的XML。所以,喜歡 在 <util:properties/>
簡單的工廠一個java.util.Properties例項可以注入。
在spring 3.0中,可以通過使用@value,對一些如xxx.properties檔案中的檔案,進行鍵值對的注入,例子如下:
- < beans xmlns = “http://www.springframework.org/schema/beans”
- xmlns:xsi = “http://www.w3.org/2001/XMLSchema-instance”
- xsi:schemaLocation =“http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.0.xsd“ >
- < bean id = “propertyConfigurer” class = “org.springframework.beans.factory.config.PropertyPlaceholderConfigurer” >
- < property name = “locations” >
- < list >
- < value > classpath:test.properties </ value >
- </ list >
- </ property >
- </ bean >
建立test.properties
abc = 123
4。
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- @RequestMapping(“/ admin / images”)
- @Controller
- public class ImageAdminController {
- private String imageDir;
- @Value(“$ {abc}”)
- public void setImageDir(String val){
- 這個 .imageDir = val
- }
- }
有時候需要從屬性檔案中載入配置,以前的方式是這樣的:
- < bean id = “jdbcProperties” class = “org.springframework.beans.factory.config.PropertyPlaceholderConfigurer” >
- < property name = “locations” >
- < list >
- < value > classpath *:/ spring / jdbc.properties </ value >
- </ list >
- </ property >
- </ bean >
最近發現這樣也可以,程式碼更整潔:
- < context:property-placeholder location = “classpath:spring / jdbc.properties” />
在豆定義中依然可以通過“$ {}”這種方式來去值:
- < bean id = “dataSource” class = “org.apache.commons.dbcp.BasicDataSource” >
- < property name = “driverClassName” value = “$ {jdbc.driverClassName}” />
- < property name = “url” value = “$ {jdbc.url}” />
- < property name = “username” value = “$ {jdbc.username}” />
- < property name = “password” value = “$ {jdbc.password}” />
- < property name = “initialSize” value = “$ {jdbc.initialSize}” />
- < property name = “maxActive” value = “$ {jdbc.maxActive}” />
- < property name = “maxIdle” value = “$ {jdbc.maxIdle}” />
- < property name = “minIdle” value = “$ {jdbc.minIdle}” />
- </ bean >
<context:property-placeholder
... />
是與PropertyPlaceholderConfigurer相當的XML。所以,喜歡 在 <util:properties/>
簡單的工廠一個java.util.Properties例項可以注入。
相關文章
- Spring配置使用註解注入beanSpringBean
- spring註解開發(一)Bean注入SpringBean
- 省掉bean自定義spring mvc註解注入json值BeanSpringMVCJSON
- Spring-註解注入Spring
- Spring4.0MVC學習資料,註解自動掃描bean,自動注入bean(二)SpringMVCBean
- SpringBoot基礎篇Bean之條件注入之註解使用Spring BootBean
- Spring注入:配置注入(set注入和構造器注入)與註解注入Spring
- Spring裝配Bean(五)profile註解和解決自動注入的歧義性SpringBean
- 對於@Bean注入的新理解Bean
- Spring中用註解建立bean例項SpringBean
- spring註解@lazy,bean懶載入SpringBean
- Spring系列之新註解配置+Spring整合junit+註解注入Spring
- 關於Spring的bean注入SpringBean
- 面試官:展開說說,Spring中Bean物件是如何通過註解注入的?面試SpringBean物件
- 【Spring註解驅動開發】在@Import註解中使用ImportBeanDefinitionRegistrar向容器中註冊beanSpringImportBean
- Spring中Bean及@Bean的理解SpringBean
- 【Spring 註解】@Configuration和@BeanSpringBean
- spring通過註解註冊bean的方式+spring生命週期SpringBean
- 【Spring註解驅動開發】在@Import註解中使用ImportSelector介面匯入beanSpringImportBean
- Spring注入Bean的幾種方式SpringBean
- spring常用的一些註解以及註解注入總結Spring
- Spring框架系列(二)之Bean的註解管理Spring框架Bean
- Spring的Bean生命週期中@PostConstruct註解SpringBeanStruct
- Spring中bean的四種注入方式SpringBean
- spring注入bean的幾種策略模式SpringBean模式
- Spring核心系列之Bean的注入SpringBean
- 【Spring註解開發】元件註冊-使用@Configuration和@Bean給容器中註冊元件Spring元件Bean
- 解決Spring中singleton中注入prototype Bean的問題SpringBean
- 基於註解的spring 在靜態方法中使用注入的類Spring
- Spring 原始碼分析之 bean 依賴注入原理(注入屬性)Spring原始碼Bean依賴注入
- Spring關於druid使用注入的深度理解SpringUI
- Spring裝配Bean(七) Spring的執行時注入SpringBean
- Spring(使用註解配置)Spring
- Spring短生命週期bean注入長生命週期bean問題SpringBean
- 擴充套件Spring——使用 Annotation將配置資源注入到Bean中套件SpringBean
- Spring學習筆記三: 通過註解配置BeanSpring筆記Bean
- Spring 依賴注入的理解Spring依賴注入
- Spring注入bean報錯 Error creating bean with name的網上找不到的解決方案SpringBeanError