1 前言
bean 的自動裝配是指:不需要手動指定 property 的 value 值,spring 自動將匹配的屬性注入 bean。主要有如下2種方式:
- bean 標籤中 autowire 屬性:bean 內所有未手動注入的屬性將自動匹配並注入,有 byType 和 byName 2種匹配方式
- @Autowire 註解:當 @Autowire 加在屬性上時,該屬性將自動匹配並注入;當 @Autowire 加在方法上時,該方法將自動調用,其入口參數爲 IOC 容器中匹配的 bean
注意事項:
- 只有非字面量(非基本數據類型及其封裝類)的屬性才能自動裝配,並且 byType 類型自動裝配支持兼容性,即允許將子類對象賦值給 bean 的某屬性(此屬性爲父類類型)
- @Autowire 在匹配時,先採用 byType 方式,再採用 byName 方式
- 當 @Autowire 沒有匹配到 bean 時,可以採用 @Autowire(required=false) 允許程序不匹配成功,避免報錯
- 當 @Autowire 匹配到多個 bean 時,可以採用 @Qualifier(value="beanId") 指定需要注入的 bean
- 所有註解在容器初始化的時候自動匹配並注入
2 bean 標籤中 autowire 屬性
2.1 byType
按照屬性類型進行匹配,需要注意:配置文件(xml文件)中匹配的 bean 要求具有唯一性,即此類型的 bean 僅有一個。
Car.java
package com.test;
public class Car {
private String cbrand;
private Engine engine;
public String getCbrand() {
return cbrand;
}
public void setCbrand(String cbrand) {
this.cbrand = cbrand;
}
public Engine getEngine() {
return engine;
}
public void setEngine(Engine engine) {
this.engine = engine;
}
@Override
public String toString() {
return "Car [cbrand=" + cbrand + ", engine=" + engine + "]";
}
}
Engine.java
package com.test;
public class Engine {
private String ebrand;
public String getEbrand() {
return ebrand;
}
public void setEbrand(String ebrand) {
this.ebrand = ebrand;
}
@Override
public String toString() {
return "Engine [ebrand=" + ebrand + "]";
}
}
applicationContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="car" class="com.test.Car" autowire="byType">
<property name="cbrand" value="奧迪"></property>
</bean>
<bean id="eng" class="com.test.Engine">
<property name="ebrand" value="雅閣"></property>
</bean>
</beans>
Engine 類型的 bean 具有唯一性。
Test.java
package com.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
Car car=ac.getBean("car",Car.class);
System.out.println(car);
}
}
運行結果:
Car [cbrand=奧迪, engine=Engine [ebrand=雅閣]]
2.2 byName
按照屬性名稱進行匹配,需要注意:匹配的 bean 的 id 與屬性名要一致。
applicationContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="car" class="com.test.Car" autowire="byName">
<property name="cbrand" value="奧迪"></property>
</bean>
<bean id="engine" class="com.test.Engine">
<property name="ebrand" value="雅閣"></property>
</bean>
</beans>
3 @Autowire 註解
@Autowire 可以加在屬性上,也可以加在方法上,並在容器初始化時自動匹配並注入。
首先需要導入如下 jar 包,並且 xml 文件需要導入 context 命名空間。
spring-aop-4.0.0.RELEASE.jar
本節主要介紹 Car.java 和 applicationContext.xml,對於 Engine.java 和 Test.java 同上。
3.1 @Autowire 加在屬性上
3.1.1 基本應用
Car.java
package com.test;
import org.springframework.beans.factory.annotation.Autowired;
public class Car {
private String cbrand;
@Autowired
private Engine engine;
public String getCbrand() {
return cbrand;
}
public void setCbrand(String cbrand) {
this.cbrand = cbrand;
}
@Override
public String toString() {
return "Car [cbrand=" + cbrand + ", engine=" + engine + "]";
}
}
注意:engine 屬性添加了 @Autowired 註解,並且其沒有 getter 方法和 setter 方法。
applicationContext.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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="com.test"></context:component-scan>
<bean id="car" class="com.test.Car">
<property name="cbrand" value="奧迪"></property>
</bean>
<bean id="engine" class="com.test.Engine">
<property name="ebrand" value="雅閣"></property>
</bean>
</beans>
注意:base-package屬性指定了需要掃描包,掃描包中所有類,併爲帶 @Autowired 註解的屬性和方法自動裝配。
運行結果:
Car [cbrand=奧迪, engine=Engine [ebrand=雅閣]]
3.1.2 @Autowire(required=false)
當沒有找到匹配的 bean 時,會報錯,如下:
NoSuchBeanDefinitionException: No qualifying bean of type [com.test.Engine] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
此時,可以在屬性前設置 @Autowire(required=false),允許屬性爲空,運行結果如下:
Car [cbrand=奧迪, engine=null]
3.1.3 @Qualifier(value="beanId")
當匹配的到多個 bean 時,會報錯,如下:
NoUniqueBeanDefinitionException: No qualifying bean of type [com.test.Engine] is defined: expected single matching bean but found 2: engine1,engine2
此時,可以採用 @Qualifier(value="beanId") 註解指定需要注入的 bean。
Car.java
package com.test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class Car {
private String cbrand;
@Autowired
@Qualifier(value="engine2")
private Engine engine;
public String getCbrand() {
return cbrand;
}
public void setCbrand(String cbrand) {
this.cbrand = cbrand;
}
@Override
public String toString() {
return "Car [cbrand=" + cbrand + ", engine=" + engine + "]";
}
}
applicationContext.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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="com.test"></context:component-scan>
<bean id="car" class="com.test.Car">
<property name="cbrand" value="奧迪"></property>
</bean>
<bean id="engine1" class="com.test.Engine">
<property name="ebrand" value="雅閣"></property>
</bean>
<bean id="engine2" class="com.test.Engine">
<property name="ebrand" value="邁騰"></property>
</bean>
</beans>
運行結果:
Car [cbrand=奧迪, engine=Engine [ebrand=邁騰]]
3.2 @Autowire 加在方法上
3.2.1 基本應用
本節僅介紹 Car.java,其他類和配置文件同3.1.1節。
Car.java
package com.test;
import org.springframework.beans.factory.annotation.Autowired;
public class Car {
private String cbrand;
private Engine engine;
@Autowired
public void addEngine(Engine engine) {
System.out.println("調用了 addEngine 方法");
this.engine=engine;
}
public String getCbrand() {
return cbrand;
}
public void setCbrand(String cbrand) {
this.cbrand = cbrand;
}
@Override
public String toString() {
return "Car [cbrand=" + cbrand + ", engine=" + engine + "]";
}
}
注意:在 addEngine(Engine engine) 方法上加了 @Autowired 註解,方法名可以隨意定,在 IOC 容器初始化時將自動調用此方法,並在容器中匹配 Engine 類型(或 id 爲 engine)的 bean 傳給該方法,作爲入口參數。
3.2.2 @Autowire(required=false)
當沒有找到匹配的 bean 時,可以在屬性前設置 @Autowire(required=false),允許屬性爲空,運行結果如下:
Car [cbrand=奧迪, engine=null]
3.2.3 @Qualifier(value="beanId")
本節僅介紹 Car.java,其他類和配置文件同3.1.3節。
當匹配的到多個 bean 時,可以採用 @Qualifier(value="beanId") 註解指定需要注入的 bean。
Car.java
package com.test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class Car {
private String cbrand;
private Engine engine;
@Autowired()
@Qualifier(value="engine2")
public void addEngine(Engine engine) {
System.out.println("調用了 addEngine 方法");
this.engine=engine;
}
public String getCbrand() {
return cbrand;
}
public void setCbrand(String cbrand) {
this.cbrand = cbrand;
}
@Override
public String toString() {
return "Car [cbrand=" + cbrand + ", engine=" + engine + "]";
}
}
運行結果:
調用了 addEngine 方法
Car [cbrand=奧迪, engine=Engine [ebrand=邁騰]]