从Spring2.5开始,增加了使用注解自动装配Bean属性的新方式,类似于在XML中使用autowire属性自动装配。
使用注解方式允许更细粒度的自动装配,可以选择性的标注某一个属性来对其自动装配。
Spring容器默认禁用注解装配,启用方式:使用Spring的context命名空间配置中的
Spring 3 支持三种用于自动装配的注解:
Spring自带的@Autowired注解
JSR-330的@Inject注解
JSR-250的@Resource注解
通常使用@Autowired标注setter方法,Spring会尝试对该方法执行byType自动装配,还可以使用@Autowired标注需要自动装配Bean引用的任意方法,包括构造器,也可以使用@Autowired直接标注属性,并删除setter方法,且不受private权限的影响。
应用中必须确保有一个Bean适合装配到@Autowired注解所标注的属性或参数中,如果没有匹配的Bean,就会出错(在之前的版本中,如果有多个可以匹配的Bean也会出错,但是在5.0.7版本中不会出错),解决方案如下:
可选的自动装配:设置@Autowired的required属性为false。
限定歧义性的依赖:@Qualifier注解,缩小自动装配的候选Bean的范围。
创建自定义的限定器:定义一个注解,使用@Qualifier注解作为它的元注解。
Java 依赖注入规范JSR-330制定了通用依赖注入模型。@Inject注解是JSR-330的核心部件,可以完全替代Spring的@Autowired注解。
和@Autowired注解一样,@Inject可以用来自动装配属性、方法和构造器,不同的是,@Inject没有required属性,因此@Inject所标注的依赖属性必须存在,否则抛出异常。
@Inject除了可直接注入一个引用,还可以注入一个Provider,Provider接口可实现Bean引用的延迟注入,以及注入Bean的多个实例。
限定@Inject所标注的属性——为消除注解导致Bean定义的歧义,类似@Autowired的@Qualifier,@Inject对应有@Name注解,通过Bean的ID来标识可选择的Bean。
创建自定义的JSR-330 Qualifier——JSR330 支持使用 javax.inject包中的@Qualifier注解来创建自定义的限定注解器,就像使用Spring的@Qualifier来创建自定义注解一样。
Spring 3引入了@Value装配注解来装配String类型以及基本类型的值,可以直接标注属性、方法或者参数。如:
@Value("memory")
private String song;
传入@Value的String类型的参数只是一个表达式,它计算的结果可以是任意类型,所以@Value可以标注任意类型的属性。
借助SpEL表达式,@Value成为强大的装配可选方案,因为可以在运行期通过SpEL动态计算复杂表达式的值并把结果装配到Bean的属性中。如:
@Value("#{properties.myFavoriteSong}")
private String song;
给出一个导弹发射的接口:
package com.li.autowire;
/*导弹接口*/
public interface IMissile {
void fire();
}
给出一个实现导弹发射接口的导弹实现类:
package com.li.autowire;
/*导弹类,实现导弹接口*/
public class Missile implements IMissile {
@Override
public void fire() {
System.out.println("The missile is fired...");
}
}
一个无人机类,内部装配有导弹:
package com.li.autowire;
import java.io.File;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/*无人机类*/
public class Uav {
/*无人机装配有导弹*/
private IMissile missile;
@Value("X-2")
private String type;
public IMissile getMissile() {
return missile;
}
public void setMissile(IMissile missile) {
this.missile = missile;
}
public Uav(IMissile missile) {
super();
this.missile = missile;
}
public Uav() {
super();
}
public void attack() {
missile.fire();
}
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("com"+File.separator+"li"+File.separator+"autowire"+File.separator+"uav.xml");
Uav uav=(Uav)ctx.getBean("uav");
uav.attack();
}
}
Spring XML配置文件,由于我们使用注解来装配Bean,所以在此文件中只给出Bean的定义,需要注意的是,要开启注解,要使用context命名空间,应根元素添加context命名空间的声明。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
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">
<context:annotation-config>context:annotation-config>
<bean id="missile" class="com.li.autowire.Missile">bean>
<bean id="m" class="com.li.autowire.Missile">bean>
<bean id="uav" class="com.li.autowire.Uav">bean>
beans>
直接在属性上使用注解进行标注,此时可以省略掉该属性的getter和setter方法了:
@Autowired
private IMissile missile;
如果不存在合适类型的Bean,可以不要求:
@Autowired(required=false)
private IMissile missile;
如果存在多个能够匹配到的Bean,那么使用Spring自带的@Qualifier(javax.inject也有此注解,但是不是)可以缩小Bean的范围:
@Autowired
@Qualifier("m")
private IMissile missile;
上面的 “m” 即为Bean的id,也可以在XML配置文件中给Bean添加一个标记,使用标记来限定:
<bean id="missile" class="com.li.autowire.Missile">bean>
<bean id="m" class="com.li.autowire.Missile">
<qualifier value="simple">qualifier>
bean>
<bean id="uav" class="com.li.autowire.Uav">bean>
@Autowired
@Qualifier("simple")
private IMissile missile;
要使用@Inject注解首先要有 javax.inject JAR包,而该JAR包在JavaSE项目中是没有的,存在于JavaEE项目,JavaEE版本的Eclipse中带有此JAR包,我们可以把它放进工程里面去。
使用
@Inject
private IMissile missile;
我们给无人机类添加一个成员变量,直接使用@Value注入一个固定值。
@Value("B-2")
private String type;