Spring的自动装配可通过<beans/>元素的default-autowire属性指定,也可通过<bean>元素的autowire属性指定。自动装配可以指定到单独的Bean,同一个Spring容器中可以让某些Bean使用自动装配,而另一些Bean不使用自动装配。
使用autowire属性配置自动装配,autowire可以设置如下值:
1)no:不使用自动装配。Bean依赖必须通过ref元素定义。也是Spring默认配置。
其中id属性与属性同名的Bean来完成注入,如果没有找到匹配的Bean实列,则Spring不会进行注入。
如果有多个相同类型的Bean,就会抛出一个异常;如果没有匹配的Bean,则什么都不会发生。
4)constructor:与byType类似,区别是用于构造注入的参数。如果BeanFactory没有符合该Bean的构造器,则会注入异常。
5)autodetect:BeanFactory根据Bean内部结构,决定使用constructor或者byType。如果含有一个默认的构造器,就会应用byType。
byName规则
byName规则是指通过名字注入依赖关系,还是使用“人”与“斧子”的列子,假如Bean Chinese 包含setAxe()方法,而Spring中拥有ID为“axe”的Bean,这样Spring容器会将斧子axe注入到人Chinese中。
<!-- 将 stoneAxe通过byName注入chinese中的axe属性-->
<bean id="chinese" class="com.custle.spring.Chinese" autowire="byName"/>
<!-- 将StoneAxe交给Srping管理 -->
<bean id="axe" class="com.custle.spring.StoneAxe"/>
在Chinese类中定义setAxe()方法:
package com.custle.spring;
public class Chinese implements Person {
private Axe axe;
//构造器注入所需要的斧子
public Chinese(Axe axe) {
this.axe = axe;
}
public Chinese() {
}
//注意该set方法后的名字与Bean中定义的ID为axe相同
public void setAxe(Axe axe) {
this.axe = axe;
}
@Override
public void useAxe() {
System.out.println(axe.chop());
}
}
这样就通过byName属性将石斧注入到Chinese中。接下来看一下注解用法;
首先在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/springcontext.xsd">
<!-- 扫描使用注释的包 -->
<context:component-scan base-package="com.custle.spring"/>
<!-- 声明使用byName注入-->
<bean id="chinese" class="com.custle.spring.Chinese" autowire="byName"/>
</beans>
在StoneAxe类通过@Component(value="stone")注释将其交由Spring管理;
@Component(value="stone")
public class StoneAxe implements Axe {
@Override
public String chop() {
return "使用石斧砍材";
}
}
在Chinese中通过@Resource(name="stone")或者@Autowired、@Qualifier("stone")使用;
package com.custle.spring;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class Chinese implements Person {
// @Resource(name="stone") 或者直接使用该注释
@Autowired
@Qualifier("stone")
private Axe axe;
static{
System.out.println("Chinese被实列化");
}
//构造器注入所需要的斧子
public Chinese(Axe axe) {
this.axe = axe;
}
public Chinese() {
}
public void setAxe(Axe axe) {
this.axe = axe;
}
@Override
public void useAxe() {
System.out.println(axe.chop());
}
}
测试代码:
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext-spring.xml");
Chinese chinese = (Chinese)applicationContext.getBean("chinese");
chinese.useAxe();
}
控制台输出:
使用石斧砍材
在这里附带说一下使用@Resource注释的装配顺序:
当@Resource后面没有任何内容时,默认使用byName的属性去匹配Bean,找不到Bean时再按照byType去匹配Bean;当指定了装配类型就按照指定的装配类型去匹配Bean,若没有找到匹配的Bean则会产生异常。
@Autowired和@Resource注释的区别:
@Autowired默认使用byType方式去装配Bean,而@Resource是使用byName方式去装配Bean。@Resource是属于JAVA的注解,而@Autowired是属于Spring的注解。
byType规则
byType规则,指根据类型匹配来注入依赖关系。假如Chinese实列有setAxe(Axe axe)方法,而Spring配置文件中拥有Axe类型的实列,则可以将Axe类型的实列注入到Chinese实列中。若Spring中不含有Axe类型的实列,也不会发生异常。但是当Spring容器中含有多个Axe类型的实列则会发生异常。
现将配置类型放置全局中,所有该<beans>下的子元素<bean>都满足该装配方式:
<?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/springcontext.xsd"
default-autowire="byType">
<!-- 扫描使用注释的包 -->
<context:component-scan base-package="com.custle.spring"/>
</beans>
由于使用了byType的配置方式,将StoneAxe交由Spring容器管理时,直接使用@Component即可,无须定义name;在Chinese实列中使用@Resource和@Autowired均可。
在某些情况下,可以限制Bean作为自动装配的候选者,则可以使用autowire-candidate="false"即可将该Bean限制在自动装配范围之外。或者在<beans>元素中使用default-autowire-candidates="false"即可将该<beans>下所有的子元素<bean>限制在自动装配范围之外。