Spring提供四种自动装配策略(针对XML配置):
1、byName :把与bean的属性具有相同名字(或者ID)的其他Bean自动装配到Bean的对应属性中。如果没有跟属性的名字相匹配的Bean,则该属性不进行装配。
2、byType :把与Bean的属性具有相同类型的其他Bean自动装配到Bean对应属性中,如果没有跟属性的类型相匹配的Bean,则该属性不被装配。
3、constructor :把与Bean的构造器入参具有相同类型的其他Bean自动装配到Bean构造器对应入参中。
4、autodetect :首先使用constructor进行自动装配。如果失败,再尝试使用byType进行自动装配。
一、byName自动装配
<!--Instrument Bean的sgtPeppers属性的名字是一样的-->
<bean id="instr" class="org.springaction.Instrument">
<property name="name" value="lisi"/>
<property name="sgtPeppers" ref="sgtPeppers"/>
</bean>
<bean id="sgtPeppers" class="org.springaction.SgtPeppers"/>
byName自动装配遵循一项约定:为属性自动装配ID与该属性的名字相同的Bean。
<!--Instrument Bean配置autowire属性,可以自动装配,减少XML-->
<bean id="instr" class="org.springaction.Instrument" autowire="byName">
<property name="name" value="lisi"/>
</bean>
<bean id="sgtPeppers" class="org.springaction.SgtPeppers"/>
二、byType自动装配
使用byType自动装配时,会寻找一个Bean的类型与属性的类型相匹配。
<!--Instrument Bean配置autowire属性按照byType自动装配,-->
<bean id="instr" class="org.springaction.Instrument" autowire="byType">
<property name="name" value="lisi"/>
</bean>
<bean id="sgt" class="org.springaction.SgtPeppers"/>
如果Spring找到多个Bean,它们的类型与需要自动装配的属性的类型都是相匹配,Spring会抛出异常。所以应用只允许存在一个Bean与需要自动装配的属性类型相匹配。解决办法:
1、标识一个首选Bean
<bean id="instr" class="org.springaction.Instrument" autowire="byType">
<property name="name" value="lisi"/>
</bean>
<bean id="sgtPeppers" class="org.springaction.SgtPeppers"/>
<!--primary用来标识首选Bean,但是它的默认值是true。所以将其他非首选的Bean的primary设置为false-->
<bean id="cdPlat" class="org.springaction.CDPlat" primary="false"/>
2、排除某些Bean
<!--设置autowire-candidate属性为false,会排除该Bean。自动装配时会忽略该Bean的候选资格-->
<bean id="cdPlat" class="org.springaction.CDPlat" autowire-candidate="false"/>
三、constructor自动装配
它也是根据相同类型进行注入,通过构造器注入来配置Bean,使用constructor装配,可以移除<\constructor-arg>元素。
<bean id="instr" class="org.springaction.Instrument" autowire="constructor">
<property name="name" value="lisi"/>
</bean>
四、默认自动装配
如果需要为Spring应用上下文中的每个Bean(或者其中的大多数)配置相同的autowire。那么可以在根元素<\beans>上增加一个属性:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
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.xsd"
default-autowire="byName">
默认情况下,default-autowire属性被设置为none。标识所有Bean都不使用自动装配,除非Bean自己配置了autowire属性。
default-autowire应用于指定Spring配置文件中的所有Bean。而不是应用上下文中所有的Bean。可以每个配置文件都有自己的默认自动装配策略。
可以使用<\bean>元素的autowire属性来覆盖<\beans>元素所配置的默认自动装配策略。
五、混合使用自动装配和显式装配
<bean id="instr" class="org.springaction.Instrument" autowire="byType">
<property name="name" value="lisi"/>
<property name="sgtPeppers" ref="sgtPeppers"/>
</bean>
<bean id="sgtPeppers" class="org.springaction.SgtPeppers"/>
混合使用自动装配和手工装配可以解决使用byType自动装配策略可能产生的装配不确定问题。显式装配可以覆盖自动装配。
使用constructor自动装配策略时,必须让Spring自动装配构造器的所有入参,不能混合使用constructor自动装配策略和<\constructor-arg>元素。
二、使用注解自动装配(基于注解)
Spring容器默认禁用注解装配,在使用前需要在Spring配置中启用:
<!--能够指导Bean装配,但是仍需要使用<bean>元素显式定义Bean,被<context:component-scan取代,既能自动装配,也能实现Bean的定义>-->
<context:annotation-config/>
1、使用@Autowired
当使用注解自动装配,可以移除<\property>元素和<\constructor-arg>元素。Spring会尝试对该方法执行byType自动装配。不仅能标注构造器、Setter方法,也可以标注任意的方法
@Autowired
public Instrument(CompactDisc sgtPeppers){
this.sgtPeppers=sgtPeppers;
}
@Autowired
public void setSgtPeppers(CompactDisc sgtPeppers) {
this.sgtPeppers = sgtPeppers;
}
@Autowired
public void hearInst(CompactDisc sgtPeppers){
this.sgtPeppers=sgtPeppers;
}
也可以直接标注属性,不会受到private影响,并删除Setter方法:
@Autowired
private CompactDisc sgtPeppers;
如果没有匹配的Bean,或者存在多个匹配的Bean。@Autowire注解会遇到麻烦。
1、没有匹配的bean(可选的自动装配)
默认情况下,@Autowire所标注的属性或参数必须是可装配的,如果没有Bean可以装配到所标注的属性中,自动装配就会失败。
可以通过设置@Autowire的required属性为false来配置自动装配是可选的:
@Autowired(required = false)
private CompactDisc sgtPeppers;
在这里如果没有查找到与之匹配的类型为CompactDisc 的Bean,应用也不会发生问题,而属性值会被设置为null。
@Autowired(required = true)
public Instrument(CompactDisc sgtPeppers){
this.sgtPeppers=sgtPeppers;
}
当使用构造器装配时,只有一个构造器可以将required属性设置为true。其他构造器只能设置为false。
当标注多个构造器时,Spring容器会从所有满足装配条件的构造器中选择入参最多的那个构造器。
2、存在多个匹配的Bean(限定歧义性的依赖)
@Qualifier注解是使用限定符的主要方式,可以与@Autowire和@Inject协同使用,在注入时指定想要注入进去的是那个bean。
@Autowired
//参数就是要注入的bean的ID
@Qualifier("sgtPeppers")
public void setSgtPeppers(CompactDisc sgtPeppers) {
this.sgtPeppers = sgtPeppers;
}
@Inject注解和@Autowire注解一样,可以用来自动装配属性、方法和构造器;不同的是@Inject没有required属性,因此,所标注的依赖关系必须存在,否则抛出异常。
@Inject使用@Named注解限定
@Inject
@Named("sgtPeppers")
public void setSgtPeppers(CompactDisc sgtPeppers) {
this.sgtPeppers = sgtPeppers;
}
使用注解装配简单值
使用@Value注解可以装配String类型的值和基本类型的值。
可以直接标注某个属性、方法或者方法参数
public class Student {
//不需要setter方法
@Value("${test.age}")
private int age;
@Value("${test.name}")
private String name;
}
XML配置
<context:property-placeholder location="testvalue.properties"/>
<bean id="student" class="org.springaction.Student"/>
传入@Value的String类型的参数只是一个表达式,它的计算结果可以是任意类型,因此@Value可以标注任意类型的属性。
可以在运行期使用SpEL动态计算复杂表达式的值并把结果装配到Bean的属性中。