Spring的《注解装配》- @autowired

来源:互联网 发布:网络布线怎么报价单 编辑:程序博客网 时间:2024/05/01 14:18

这篇博客主要介绍通过@autowired 注解来装配bean,包括以下内容:
1. 通过属性域注入
2. 通过set方法或则其他方法注入
3. 通过构造器方法注入
4. @autowired 的required属性
5. @autowired 的限定器@Qualifier

1. 通过属性域注入

下面通过一个实例来说明@autowired 注解实现属性域注入:
(1)entity
蛋糕类

package spring.ch2.topic2;/** * Created by louyuting on 17/1/20. * 注入属性,记得属性必须要写setter方法  不然就会抛出异常,注入失败. * 蛋糕类 */public class Cake {    private String name = "";    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}

厨师类

package spring.ch2.topic2;import org.springframework.beans.factory.annotation.Autowired;/** * Created by louyuting on 17/1/22. */public class Chief {    @Autowired    private Cake cake = null;//自动注入的就不需要setter方法了    private String name = "";    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Cake makeOneCake() {        System.out.println(getName() + " make " + cake.getName());        return cake;    }}

这里需要注意的是,虽然我们的cake属性域是赋值为null,但是当spring容器启动时,j就会通过@Autowired标签注入cake对象。

(2)配置文件

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:p="http://www.springframework.org/schema/p"       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.1.xsd        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">    <bean id="blueberryCheese"          class="spring.ch2.topic2.Cake"          p:name="blueberryCheese---Cake" scope="prototype">    </bean>    <bean id="jack"          class="spring.ch2.topic2.Chief"          p:name="jack">    </bean></beans>

虽然我们上面这里定义了两个bean,但是jack那个bean不再需要通过标签来注入id为blueberryCheese这个bean,而是通过Chief里面的@Autowired标签来完成自动注入。

(3)测试类:

package spring.ch2.topic2;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationContext;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;/** * Created by louyuting on 17/1/20. * 注入List和Set */@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = {"/spring/ch2/topic2/ApplicationContext-test.xml"})public class ChiefTest {    @Autowired    private ApplicationContext applicationContext;    @Test    public void testChief(){        Chief jack = (Chief)applicationContext.getBean("jack");        jack.makeOneCake();    }}

(4)运行结果:

jack make blueberryCheese---Cake

从运行结果可知,通过@autowired 属性域注入成功。

2. 通过set方法或则其他方法注入

上一节讲了将@autowired 注解添加到属性域上来实现自动注入。这一节讲另外一种方式:通过将注解加在set方法上来实现注入。
(1)entity
蛋糕类(不变)

package spring.ch2.topic2;/** * Created by louyuting on 17/1/20. * 注入属性,记得属性必须要写setter方法  不然就会抛出异常,注入失败. * 蛋糕类 */public class Cake {    private String name = "";    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}

厨师类:取消cake属性上面的注解,将autowired注解加在cake的set方法上。这也是和属性注入的区别所在。

package spring.ch2.topic2;import org.springframework.beans.factory.annotation.Autowired;/** * Created by louyuting on 17/1/22. */public class Chief {    private Cake cake = null;    private String name = "";    public Cake getCake() {        return cake;    }    @Autowired    public void setCake(Cake cake) {        this.cake = cake;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Cake makeOneCake() {        System.out.println(getName() + " make " + cake.getName());        return cake;    }}

(3)配置文件和测试用例均不变。

(4)运行结果:

jack make blueberryCheese---Cake

可知:通过set方法注入成功。其实除了set方法以外,我们把注解放在任何方法上都可以成功注入成功,当然方法的实现必须和set方法一样,只是名字不必严格规定。比如:

@Autowired  public void injectCake(Cake cake) {      this.cake = cake;  }  

这样也可以成功注入。

3. 通过构造器方法注入

下面介绍通过构造器注入实例:
(1)entity
蛋糕类(不变)

厨师类:注意,这里我删除了set方法,并且添加了构造器,在构造器上加了注解:@Autowired

package spring.ch2.topic2;import org.springframework.beans.factory.annotation.Autowired;/** * Created by louyuting on 17/1/22. */public class Chief {    private Cake cake = null;    private String name = "";    @Autowired    public Chief(Cake cake) {        this.cake = cake;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Cake makeOneCake() {        System.out.println(getName() + " make " + cake.getName());        return cake;    }}

测试类和配置文件均不变。

输出是:

jack make blueberryCheese---Cake

可知构造器注入成功。

上面已经介绍了3种通过@autowired 注解实现自动注入的方法。下面介绍在@autowired 里面添加参数required的含义:

4.@autowired 的required属性

required属性表示注入对象是否必须非空。@autowired注解默认是非空的(即默认required是true的)。如果我想允许注入空对象,必须配置 @autowired(required=false)。

比如我有如下的chief类:

package spring.ch2.topic2;import org.springframework.beans.factory.annotation.Autowired;/** * Created by louyuting on 17/1/22. */public class Chief {    @Autowired    private Cake cake = null;//自动注入的就不需要setter方法了    private String name = "";    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Cake makeOneCake() {        System.out.println(getName() + " make " + cake.getName());        return cake;    }}

这个时候在xml中不配置Cake类的bean, 运行测试类那么就会抛出异常:
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [spring.ch2.topic2.Cake] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) ~
……

要想允许注入null对象,就必须加上属性:
@Autowired(required=false)表示允许注入空对象,这样不论是否存在cake类的bean,都会注入成功。

还有一点就是当出现多构造器注入的情况,虽然我们都可以使用@autowired标签,但是需要把required都弄成是false,不然抛异常。而且当出现多构造器注入时,注入成功的是注入对象输入参数最多的那个构造器。

5. @autowired 的限定器@Qualifier

这一节详细讨论一下配合@autowired一起使用的限定器@Qualifier。当出现多个可选择装配的bean时,@Qualifier可以指定装配的id名称。通过例子说明:
(1)entity
蛋糕类(不变)

package spring.ch2.topic2;/** * Created by louyuting on 17/1/20. * 注入属性,记得属性必须要写setter方法  不然就会抛出异常,注入失败. * 蛋糕类 */public class Cake {    private String name = "";    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}

厨师类:

package spring.ch2.topic2;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;/** * Created by louyuting on 17/1/22. */public class Chief {    @Qualifier("cake")    @Autowired(required = false)    private Cake cake = null;    private String name = "";    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Cake makeOneCake() {        System.out.println(getName() + " make " + cake.getName());        return cake;    }}

厨师类这里需要注意的是,由于配置文件可能出现多个满足Cake的bean,因此我们在chief里面使用限定器@Qualifier,限定了cake属性的注入对象只能够是bean id是cake的bean。

(2)配置文件:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:p="http://www.springframework.org/schema/p"       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.1.xsd        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">    <bean id="blueberryCheese"          class="spring.ch2.topic2.Cake"          p:name="blueberryCheese---Cake" scope="prototype">    </bean>    <bean id="cake"          class="spring.ch2.topic2.Cake"          p:name="second---Cake" scope="prototype">    </bean>    <bean id="jack"          class="spring.ch2.topic2.Chief"          p:name="jack">    </bean></beans>

配置文件需要注意的地方是:我们为了测试上面的例子,故意定义了两个Cake类型的bean

(3)测试类:

package spring.ch2.topic2;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationContext;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;/** * Created by louyuting on 17/1/20. * 注入List和Set */@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = {"/spring/ch2/topic2/ApplicationContext-test.xml"})public class ChiefTest {    @Autowired    private ApplicationContext applicationContext;    @Test    public void testChief(){        Chief jack = (Chief)applicationContext.getBean("jack");        jack.makeOneCake();    }}

(4)输出:

jack make second---Cake

可知注入的是id是cake的bean。

完整源代码下载 github地址

0 0