2. 使用注解装配

使用注解装配

从Spring2.5开始,增加了使用注解自动装配Bean属性的新方式,类似于在XML中使用autowire属性自动装配。

使用注解方式允许更细粒度的自动装配,可以选择性的标注某一个属性来对其自动装配。

Spring容器默认禁用注解装配,启用方式:使用Spring的context命名空间配置中的 <context:annotation-config/>元素,告诉Spring开启使用基于注解的自动装配(属性、方法和构造器)。

Spring 3 支持三种用于自动装配的注解:

  • Spring自带的@Autowired注解

  • JSR-330的@Inject注解

  • JSR-250的@Resource注解

使用@Autowired

通常使用@Autowired标注setter方法,Spring会尝试对该方法执行byType自动装配,还可以使用@Autowired标注需要自动装配Bean引用的任意方法,包括构造器,也可以使用@Autowired直接标注属性,并删除setter方法,且不受private权限的影响。

应用中必须确保有一个Bean适合装配到@Autowired注解所标注的属性或参数中,如果没有匹配的Bean,就会出错(在之前的版本中,如果有多个可以匹配的Bean也会出错,但是在5.0.7版本中不会出错),解决方案如下:

  • 可选的自动装配:设置@Autowired的required属性为false。

  • 限定歧义性的依赖:@Qualifier注解,缩小自动装配的候选Bean的范围。

  • 创建自定义的限定器:定义一个注解,使用@Qualifier注解作为它的元注解。

借助@Inject实现基于标准的自动装配

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命名空间的声明。

<?xml version="1.0" encoding="UTF-8"?>

<!-- 引用Spring的多个Schema空间的格式定义文件 -->

<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命名空间并引入xsd文件 -->
    <!-- 开启注解 -->
    <context:annotation-config></context:annotation-config>

    <!-- 只需保留Bean的定义 -->

    <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>

使用@Autowired注解

直接在属性上使用注解进行标注,此时可以省略掉该属性的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注解

要使用@Inject注解首先要有 javax.inject JAR包,而该JAR包在JavaSE项目中是没有的,存在于JavaEE项目,JavaEE版本的Eclipse中带有此JAR包,我们可以把它放进工程里面去。

使用

@Inject
 private IMissile missile;

注解中使用表达式

我们给无人机类添加一个成员变量,直接使用@Value注入一个固定值。

@Value("B-2")
private String type;

猜你喜欢

转载自blog.csdn.net/sinat_37976731/article/details/81363761