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

来源:互联网 发布:淘宝北京聚镁特商贸 编辑:程序博客网 时间:2024/05/20 18:42
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;
    }
    @required
public 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 {
@Autowired
private 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 {
@Autowired
private Dog dog ;
public Dog getDog() {
return dog;
    }
public void setDog(Dog dog) {
this.dog = dog;
    }
@Autowired
private Dog[] dogs;
public Dog[] getDogs() {
return dogs;
    }
public void setDogs(Dog[] dogs) {
this.dogs = dogs;
    }
@Autowired
private 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只
lili
zhonghua1
zhuonghua2
有ZhongHuaDog:2只
zhonghua1
zhuonghua2


    从结果里看:
使用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
原创粉丝点击