javascript
零配置 之 Spring 注解实现Bean依赖注入
轉載自??【第十二章】零配置 之 12.2 注解實現Bean依賴注入 ——跟我學spring3?
12.2? 注解實現Bean依賴注入
12.2.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”。
?
12.2.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注解。
?
12.2.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容器中查找。
總結
以上是生活随笔為你收集整理的零配置 之 Spring 注解实现Bean依赖注入的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 地下城对电脑配置要求(地下城对电脑配置)
- 下一篇: 零配置 之 Spring注解实现Bean