Spring主要提供以下兩種方法用於依賴注入
例子:
public class Communication {
private Messaging messaging;
/*
* DI via Setter
*/
public void setMessaging(Messaging messaging){
this.messaging = messaging;
}
public void communicate(){
messaging.sendMessage();
}
}
如上Communication類有一個messaging屬性,並含有setMessaging方法,那麼使用Setter方法注入的時候,只需要使用如下XML配置即可:
<?xml version="1.0" encoding="UTF-8"?>
<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-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<bean id="activeMqMessaging" class="com.websystique.spring.domain.impl.ActiveMQMessaging" />
<bean id="communication" class="com.websystique.spring.Communication">
<property name="messaging">
<ref bean="activeMqMessaging" />
</property>
</bean>
</beans>
這裡省略了ActiveMQMessaging的定義,實際上ActiveMQMessaging類是Messaging接口的一個實現類。
例子
public class Communication {
private Encryption encryption;
/*
* DI via Constructor Injection
*/
public Communication(Encryption encryption){
this.encryption = encryption;
}
public void communicate(){
encryption.encryptData();
}
}
注意以上Communication類有一個構造方法Communication(Encryption encryption),且含有一個入參,類型為Encryption,那麼使用構造方法注入的時候,XML配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<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-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<bean id="rsaEncryption" class="com.websystique.spring.domain.impl.RSAEncryption" />
<bean id="communication" class="com.websystique.spring.Communication">
<constructor-arg type="com.websystique.spring.domain.Encryption">
<ref bean="rsaEncryption" />
</constructor-arg>
</bean>
</beans>
注意,這裡省略了RSAEncryption的定義,不用在意這些細節,該類是Encryption接口的一個實現類。
另外,為了避免構造方法重載帶來的歧義,這裡指定了入參類型為com.websystique.spring.domain.Encryption。
bean的裝配有兩種方式,手動裝配和自動裝配。注意,不要混淆,bean的裝配是依賴注入的具體行為,依賴注入的時候需要根據bean的名稱或類型等進行裝配。
手動裝配:通過在<property> 或者 <constructor>標簽中使用ref屬性,在上一小節的“依賴注入”部分使用的就是手動裝配;
<!-- default example (autowire="no") -->
<bean id="driver" class="com.websystique.spring.domain.Driver">
<property name="license" ref="license"/>
</bean>
<bean id="license" class="com.websystique.spring.domain.License" >
<property name="number" value="123456ABCD"/>
</bean>
自動裝配:在<bean>標簽中使用autowire屬性;
<bean id="application" class="com.websystique.spring.domain.Application" autowire="byName"/>
本小節主要關注自動裝配,自動裝配有以下四種方式:
autowire="byName" : 根據名稱autowire="byType" : 根據類型autowire="constructor" : 根據構造方法入參類型autowire="no" : 不使用自動裝配,即默認方式,手動裝配autowire="byName"例子:
public class Application {
private ApplicationUser applicationUser;
public ApplicationUser getApplicationUser() {
return applicationUser;
}
public void setApplicationUser(ApplicationUser applicationUser) {
this.applicationUser = applicationUser;
}
@Override
public String toString() {
return "Application [applicationUser=" + applicationUser + "]";
}
}
該類有一個屬性叫applicationUser,那麼根據名稱自動裝配的XML配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<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-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- byName example -->
<bean id="application" class="com.websystique.spring.domain.Application" autowire="byName"/>
<bean id="applicationUser" class="com.websystique.spring.domain.ApplicationUser" >
<property name="name" value="superUser"/>
</bean>
</beans>
autowire="byType"例子
public class Employee {
private EmployeeAddress address;
public EmployeeAddress getAddress() {
return address;
}
public void setAddress(EmployeeAddress address) {
this.address = address;
}
@Override
public String toString() {
return "Employee [address=" + address + "]";
}
}
該類有一個屬性類型為EmployeeAddress,那麼根據類型自動裝配的XML配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<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-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- byType example -->
<bean id="employee" class="com.websystique.spring.domain.Employee" autowire="byType"/>
<bean id="employeeAddress" class="com.websystique.spring.domain.EmployeeAddress" >
<property name="street" value="112/223,SantaVila"/>
<property name="city" value="Nebraska"/>
</bean>
</beans>
autowire="constructor"例子
public class Performer {
private Instrument instrument;
public Performer(Instrument instrument){
this.instrument = instrument;
}
@Override
public String toString() {
return "Performer [instrument=" + instrument + "]";
}
}
該類有一個構造方法,入參的類型為Instrument,那麼根據構造方法自動裝配的XML配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<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-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- constructor example -->
<bean id="performer" class="com.websystique.spring.domain.Performer" autowire="constructor"/>
<bean id="instrument" class="com.websystique.spring.domain.Instrument" >
<property name="name" value="PIANO"/>
</bean>
</beans>
autowire="no"public class Driver {
private License license;
public void setLicense(License license) {
this.license = license;
}
public License getLicense() {
return license;
}
@Override
public String toString() {
return "Driver [license=" + license + "]";
}
}
該類有一個屬性license,由於我們不打算使用自動裝配功能,那麼只能使用手動裝配了,XML配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<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-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- default example (autowire="no") -->
<bean id="driver" class="com.websystique.spring.domain.Driver" autowire="no">
<property name="license" ref="license"/>
</bean>
<bean id="license" class="com.websystique.spring.domain.License" >
<property name="number" value="123456ABCD"/>
</bean>
</beans>
注意,如果不配置license的ref引用的話,license將為null。
主要涉及以下三個注解
@Autowired@Resource@Qualifier@Autowired可應用於構造方法、屬性、setter方法或配置類@Configuration的方法上,該注解根據bean的數據類型進行裝配,如果你想希望根據bean的名稱進行裝配可以使用帶name屬性的@Resource注解;另外@Qualifier注解經常與@Autowired注解結合使用,用於解決一個應用中存在多個同種類型的bean的情況,下面將給出各個注解的示例。
@Autowired(根據類型自動裝配)setter方法上
@Component("driver")
public class Driver {
private License license;
@Autowired
public void setLicense(License license) {
this.license = license;
}
@Override
public String toString() {
return "Driver [license=" + license + "]";
}
//getter
}
構造方法上
@Component("driver")
public class Driver {
private License license;
@Autowired
public Driver(License license){
this.license = license;
}
@Override
public String toString() {
return "Driver [license=" + license + "]";
}
}
屬性上
@Component("driver")
public class Driver {
@Autowired
private License license;
//getter,setter
@Override
public String toString() {
return "Driver [license=" + license + "]";
}
}
@Resource(根據名稱裝配)@Component("application")
public class Application {
@Resource(name="applicationUser")
private ApplicationUser user;
@Override
public String toString() {
return "Application [user=" + user + "]";
}
}
@Qualifier(與@Autowired結合使用,實現按名稱裝配)例子背景::存在兩個Car接口的實現類,其中一個Car接口的實現類已被注冊為bean,且name為Mustang
@Component
public class Bond {
@Autowired
@Qualifier("Mustang")
private Car car;
public void showCar(){
car.getCarName();
}
}
注意,以上例子如果不使用@Qualifier限定的話,將拋出如下異常,表明存在多個類型相同的bean:
最後提醒下,被@Autowired注解標注默認情況下能保證成功注入,如果注入不成功(往往是找不到,或存在歧義),Spring會拋出異常。當然,有時候可能會有特殊需求,不希望bean被強制裝配,那麼可以在@Autowired上添加required=false屬性,表明該bean的裝配是可選的,找不到的話,就為null吧,如下示例:
@Component("driver")
public class Driver {
@Autowired(required=false)
private License license;
//getter,setter
@Override
public String toString() {
return "Driver [license=" + license + "]";
}
}
基於以上原因,雖然@Autowired注解與@Resource功能類似,但是@Autowired還是比@Resource強大了那麼一點點,個人建議使用@Autowired注解。
http://websystique.com/spring/spring-dependency-injection-example-with-constructor-and-property-setter-xml-example/
http://websystique.com/spring/spring-beans-auto-wiring-example-using-xml-configuration/
http://websystique.com/spring/spring-dependency-injection-annotation-beans-auto-wiring-using-autowired-qualifier-resource-annotations-configuration/