5.spring注解@Required、@Autowired、@qualifier、@resource

来源:互联网 发布:学软件开发去哪里 编辑:程序博客网 时间:2024/05/20 19:47

5.1 注解概述

    用注解进行数据的配置似乎是现在越来越流行的方式,struts2、springmvc都有提供了一套基于注解的数据配置方式,这的确为我们编写代码提供了极大的便利。不过我个人还是不喜欢用注解的方式,我觉得注解的方式不够直观,而且如果类很多,需要的注解也很多,那么对于随着代码的增加,就会增加其他人阅读和维护代码的难度(纯属个人观点,也许随着工作经验的增加观点也会变化吧)。5.1.1 注解的使用    在上一篇中我们提到过一下bean的生命周期,spring容器产生bean的第一步就是读取配置xml文件,如果我们配置了注解的方式,那么容器这时候还会读取注解的信息,产生配置元数据。那么,我们需要做什么才能让容器去读取注解的配置呢?    很简单,在xml文件中加入
<context:annotation-config/>
    完整的xml文件如下(比没有用注解的xml文件多了几行xmlns和xsi)
<?xml version="1.0" encoding="UTF-8"?><beansxmlns="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/spring-context.xsd">   <context:annotation-config/>   </beans>
    在文档里面还有一段note,我觉得以后可能会用到,如下:
<context:annotation-config/> only looks for annotations on beans in the same application context in which it is defined. This means that, if you put <context:annotation-config/> in a WebApplicationContext for a DispatcherServlet, it only checks for @Autowired beans in your controllers, and not your services. <context:annotation-config/>这个注解配置是context级别的,也就是说如果你在WebApplicationContext中配置,只会对Controller有用,对其他的bean没用。

5.2 @Required

    用在set方法上,一旦用了这个注解,那么容器在初始化bean的时候必须要进行set,也就是说必须对这个值进行依赖注入。    例子:(下面的Zoo和Dog类在以后的例子中都要用到)    动物园类Zoo
public class Zoo {private Dog dog ;public Dog getDog() {return dog;    }    @requiredpublic void setDog(Dog dog) {this.dog = dog;    }}
     Dog类:
public class Dog {private String name ;private double weight ;//get  set}
    xml文件:
<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/spring-context.xsd"><context:annotation-config></context:annotation-config><bean id="zoo" class="com.example.iocContainer.Zoo"></bean><bean id="dog" class="com.example.iocContainer.Dog"></bean></beans>
    测试代码:
ApplicationContext app = new ClassPathXmlApplicationContext("spring-main.xml");Zoo zoo = (Zoo) app.getBean("zoo");
    结果:
Property 'dog' is required for bean 'zoo'

5.3@Autowired

      5.3.1使用方法在第三节里面讲到过xml文件中bean的一个属性:autowire(自动装配),这个Autowired注解和autowire也很相似,就是可以不写依赖注入的配置让容器自己寻找依赖并注入,不过这个Autowired注解只能用类别来寻找依赖并注入,不像autowire属性可以自己配置依赖寻找的方式。例子:(Dog类如上)Zoo类:
public class Zoo {@Autowiredprivate Dog dog ;public Dog getDog() {return dog;    }public void setDog(Dog dog) {this.dog = dog;    }}
    配置文件xml:
<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/spring-context.xsd"><context:annotation-config></context:annotation-config><bean id="zoo" class="com.example.iocContainer.Zoo"></bean><bean id="dog" class="com.example.iocContainer.Dog"><property name="name" value="lili"/><property name="weight" value="28.9"/></bean></beans>
    测试代码:
ApplicationContext app = new ClassPathXmlApplicationContext("spring-main.xml");Zoo zoo = (Zoo) app.getBean("zoo");System.out.println(zoo.getDog().getName()+" "+zoo.getDog().getWeight());
    结果:
lili 28.9
    从结果可以看出,spring已经完成对Zoo中依赖Dog的注入。我们修改xml配置文件,将dog的名字改为pitdog,发现也同样可以进行依赖注入,证明@Autowired注解的确应该是利用类型来寻找依赖的。    5.3.2 对集合使用@Autowired    显然,动物园里面不可能只有一条狗,那么我们改变Zoo类:里面增加了一种ZhongHuaDog的狗,是Dog的子类。
public class Zoo {@Autowiredprivate Dog dog ;public Dog getDog() {return dog;    }public void setDog(Dog dog) {this.dog = dog;    }@Autowiredprivate Dog[] dogs;public Dog[] getDogs() {return dogs;    }public void setDogs(Dog[] dogs) {this.dogs = dogs;    }@Autowiredprivate ZhongHuaDog[] zhongHuaDogs ;public ZhongHuaDog[] getZhongHuaDogs() {return zhongHuaDogs;    }public void setZhongHuaDogs(ZhongHuaDog[] zhongHuaDogs) {this.zhongHuaDogs = zhongHuaDogs;    }}
 ZhongHuaDog类:
public class ZhongHuaDog extends Dog {private String color ;public String getColor() {return color;    }public void setColor(String color) {this.color = color;    }}
    配置文件
<bean id="zoo" class="com.example.iocContainer.Zoo"></bean><bean id="dog" class="com.example.iocContainer.Dog"><property name="name" value="lili"/><property name="weight" value="28.9"/></bean><bean id="zhonghuadog1" class="com.example.iocContainer.ZhongHuaDog" parent="dog"><property name="name" value="zhonghua1"/><property name="weight" value="23.2"/><property name="color" value="red"/></bean><bean id="zhonghuadog2" class="com.example.iocContainer.ZhongHuaDog" parent="dog"><property name="color" value="red"/><property name="weight" value="22.1"/><property name="name" value="zhuonghua2"/></bean>
    测试代码:
ApplicationContext app = new ClassPathXmlApplicationContext("spring-main.xml");Zoo zoo = (Zoo) app.getBean("zoo");Dog[] dogs = zoo.getDogs();ZhongHuaDog[] zhongHuaDogs = zoo.getZhongHuaDogs();System.out.println("动物园里有Dog:"+dogs.length+"只");for(int i=0;i<dogs.length;i++){    System.out.println(dogs[i].getName());}System.out.println("有ZhongHuaDog:"+zhongHuaDogs.length+"只");for(int i=0;i<zhongHuaDogs.length;i++){    System.out.println(zhongHuaDogs[i].getName());}
    结果:
动物园里有Dog:3只lilizhonghua1zhuonghua2ZhongHuaDog:2zhonghua1zhuonghua2
    从结果里看:使用Autowired对集合进行依赖注入的时候,会将相应类型的子类也同样进行依赖注入。

5.4 @qualifier

    5.4.1 用法    假设容器里面有很多的ZhongHuaDog,但是我们的动物园里只有一条ZhongHuaDog,那么在进行依赖注入的时候就需要进行甄别,这时候就用到了@qualifier    例子:   将xml配置文件改成:(注意两个qualifier属性)
<context:annotation-config></context:annotation-config><bean id="zoo" class="com.example.iocContainer.Zoo"></bean><bean id="dog" class="com.example.iocContainer.Dog">    <property name="name" value="lili"/>    <property name="weight" value="28.9"/></bean><bean id="zhonghuadog1" class="com.example.iocContainer.ZhongHuaDog">    <qualifier value="zoo"/>    <property name="name" value="zhonghua1"/>    <property name="weight" value="23.2"/>    <property name="color" value="red"/></bean><bean id="zhonghuadog2" class="com.example.iocContainer.ZhongHuaDog" parent="dog">    <qualifier value="yesheng"/>    <property name="color" value="red"/>    <property name="weight" value="22.1"/>    <property name="name" value="zhuonghua2"/></bean>

Zoo文件改成:

public class Zoo {    private ZhongHuaDog zhongHuaDog ;    public ZhongHuaDog getZhongHuaDog() {        return zhongHuaDog;    }    @Autowired    public void setZhongHuaDog(@Qualifier("zoo") ZhongHuaDog zhongHuaDog) {        this.zhongHuaDog = zhongHuaDog;    }}

测试代码:

ApplicationContext app = new ClassPathXmlApplicationContext("spring-main.xml");Zoo zoo = (Zoo) app.getBean("zoo");System.out.println(zoo.getZhongHuaDog().getName());

结果:

zhonghua1
这说明配置了qualifier的注解,那么容器就会去寻找和注解中qualifier值相同的bean去进行注入

5.5 @Resource

我觉得这就是一个可以使用bean id进行依赖注入的Autowired。看看用法就知道了把5.4中的zoo改一下:
@Resource(name = "zhonghuadog2")private ZhongHuaDog zhongHuaDog ;public ZhongHuaDog getZhongHuaDog() {    return zhongHuaDog;}public void setZhongHuaDog( ZhongHuaDog zhongHuaDog) {    this.zhongHuaDog = zhongHuaDog;}

测试代码:

ApplicationContext app = new ClassPathXmlApplicationContext("spring-main.xml");Zoo zoo = (Zoo) app.getBean("zoo");System.out.println(zoo.getZhongHuaDog().getName());

结果:

zhonghua2
1 0