【Spring学习笔记四】-自动装配Bean

上一次博客写到Spring有两种依赖注入的方式,设值注入和构造注入,详情点击这里:http://blog.csdn.net/kevin_zhai/article/details/52184901。上述两种注入方式的例子,都是经过XML配置文件来装配Bean的。除此以外,Spring提供了一种更加方便的装配Bean的方法,即利用@Autowired注解进行自动装配。
1、@Autowired基本使用

仍是以上一次博客的代码为例。在上次的博客中,是经过配置文件来装配的。下面换成自动装配Bean。首先,在Person实现类Chinese中去掉axe的set方法,并加上@Autowired标注。代码以下:html

public class Chinese implements Person {
	
	@Autowired
	private Axe axe;  
	@Override
	public void useAxe() {
		System.out.println(axe.chop());
	}
}

Spring 经过一个 BeanPostProcessor 对 @Autowired 进行解析,因此要让 @Autowired 起做用必须事先在 Spring 容器中声明 AutowiredAnnotationBeanPostProcessor Bean。同时,在XML配置文件中,能够去掉<property>标签。配置文件以下:
java

<?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-3.0.xsd"> 
    <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>      
    <bean id="Chinese" class="com.ceshi.service.imp.Chinese">  
       <!--<property name="axe" ref="stoneAxe"/>  -->
    </bean>  
    <bean id="stoneAxe" class="com.ceshi.service.imp.StoneAxe">  
    </bean>
</beans>
运行结果:石斧砍柴好慢
那么Spring是怎样去自动装配Bean的呢?原来当Spring容器启动时,AutowiredAnnotationBeanPostProcessor 将扫描 Spring 容器中全部 Bean,当发现 Bean 中拥有@Autowired 注释时就找到和其匹配的 Bean,并注入到对应的地方中去。
2、自动装配查找模式
上面讲到Spring会自动去查找和@Autowired注解匹配的Bean,那么它是按照什么来查找的呢?其实,它是有两种查找模式,分别是按变量类型和按指定名称来查找。在默认的状况下,会按照变量类型来查找。在上面的实例中,spring容器在启动时,会去查找与axe类型相同的Bean。axe的类型是com.ceshi.service.Axe,因此当扫描到id为stoneAxe的Bean时,判断它们类型一致,会自动加载Bean进来。
可是,若是Spring上下文中存在不止一个Axe类型的Bean时,就会出现异常。此时,可使用@Qualifie注解来给变量指定名称,当Spring容器去扫描Bean时,只有Id和指定名称匹配时,才可以正确装配Bean。
仍是以上面例子为例,在Chinese加入@Qualifie注解,代码以下:

public class Chinese implements Person {
	
	@Autowired
	@Qualifier("axe")  //指定名称
	private Axe axe;  
	@Override
	public void useAxe() {
		System.out.println(axe.chop());
	}
}
若是XML文件不作任何修改的话,因为没有与指定名称相匹配的Bean,会出现BeanCreationException异常。对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-3.0.xsd"> 
    <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>      
    <bean id="Chinese" class="com.ceshi.service.imp.Chinese">  
       <!--<property name="axe" ref="stoneAxe"/>  -->
    </bean>  
<bean id="axe" class="com.ceshi.service.imp.StoneAxe">  
<!--修改Id与指定名称匹配  -->
    </bean>
</beans>
在没有匹配到对应的Bean时,若是想避免异常的出现,能够将@Autowired的required属性设置为false。对Chinese作以下修改:

public class Chinese implements Person {
	
	@Autowired(required = false)  //设置属性为false
	@Qualifier("axe")
	private Axe axe;  
	@Override
	public void useAxe() {
		System.out.println(axe.chop());
	}
}
将required属性设置为false时,Spring会尝试执行自动装配,可是若是没有匹配的Bean的话,Spring将会让这个Bean处于未装配的状态。可是,若是在代码中没有进行null检出的话,这个处于未装配状态的属性有可能会出现NullPointerException异常。
3、@Autowired和@Component共同使用
虽然用了@Autowired标注以后,省去了setter方法,可是仍是须要在XML中声明Bean。那有没有更简单的方法呢,答案是确定的。咱们能够将@Component与@Autowired标注配合使用。@Component的做用是将类自动注册到Spring容器中,至关于配置文件中的<bean id="" class=""/>
仍是上面的例子,在stoneAxe类加上@Component标注,以下:
@Component("stoneAxe")
public class StoneAxe implements Axe{

	@Override
	public String chop() {
		return "石斧砍柴好慢";
	}
}
而后,要修改配置文件。要加入下面配置:<context:component-scan base-package=” ”> ,这个配置是用来引入Spring自动扫描时的包。同时,要把原先声明的Bean去掉。修改后配置文件以下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
	xmlns:context="http://www.springframework.org/schema/context" 
    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
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> 
<!-- 加入配置  -->
    <context:annotation-config/>
    <context:component-scan base-package="com.ceshi">
    </context:component-scan>
<bean id="Chinese" class="com.ceshi.service.imp.Chinese"/>
<!-- 去掉Bean  -->
<!-- <bean id="axe" class="com.ceshi.service.imp.StoneAxe">  -->     
</beans>
这样,当Spring启动时,会扫描整个com.ceshi包,当发现有@Component标注的类时,就会将它自动加入到Spring容器中。这样,@Autowired进行自动装配时,就能够找到对应的Bean了。