spring框架——bean的自動裝配

1 前言

bean 的自動裝配是指:不需要手動指定 property 的 value 值,spring 自動將匹配的屬性注入 bean。主要有如下2種方式:

  • bean 標籤中 autowire 屬性:bean 內所有未手動注入的屬性將自動匹配並注入,有 byType 和 byName 2種匹配方式
  • @Autowire 註解:當 @Autowire 加在屬性上時,該屬性將自動匹配並注入;當 @Autowire 加在方法上時,該方法將自動調用,其入口參數爲 IOC 容器中匹配的 bean

注意事項

  1. 只有非字面量(非基本數據類型及其封裝類)的屬性才能自動裝配,並且 byType 類型自動裝配支持兼容性,即允許將子類對象賦值給 bean 的某屬性(此屬性爲父類類型)
  2. @Autowire 在匹配時,先採用 byType 方式,再採用 byName 方式
  3. 當 @Autowire 沒有匹配到 bean 時,可以採用 @Autowire(required=false) 允許程序不匹配成功,避免報錯
  4. 當 @Autowire 匹配到多個 bean 時,可以採用 @Qualifier(value="beanId") 指定需要注入的 bean
  5. 所有註解在容器初始化的時候自動匹配並注入

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=邁騰]]

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章