从spring 2.0开始,spring依次加入了对注解型元数据配置的支持。自此我们有了另外一种配置bean的方式。上篇文章中,我们对Spring支持的注解进行了大致的分类,并对其有了初步的介绍。本篇文章则对其展开较详细的说明。主要讲述依赖级别,部分属性级别则在过程中穿插使用。
本篇使用的示例代码继承之前的篇章。
依赖级别
Spring可以使用这些注解进行依赖注入,通常是自动的,或者借助一些辅助信息。也就是说,我们对Bean的定义还是采用XML的方式,而对其依赖的注入则使用注解的方式。
@Autowired
首先登场的当然是大明鼎鼎的@Autowired。从名字就可以看出来其可以“自动装配依赖”。它通过类型自动注入(byType)首先在配置文件中加入以下配置是,@Autowired生效:
- <bean
- class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean
class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
@Autowired可以标注在 字段、set方法和构造函数上,假如说我们例如我们依次有以下配置,并且已经在XML文件中有了bean的定义,以下的三种方式等价,均上自动注入依赖UserDao,可以和前篇使用xml 的注入依赖的方式比较:
- //标注在字段上。
- @Autowired
- private UserDao userDao;
//标注在字段上。
@Autowired
private UserDao userDao;
- //标注在set方法上。
- @Autowired
- public void setUserDao(UserDao userDao) {
- this.userDao = userDao;
- }
//标注在set方法上。
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
- //标注在构造函数上
- @Autowired
- public UserServiceIml3(UserDao userDao) {
- super();
- this.userDao = userDao;
- }
//标注在构造函数上
@Autowired
public UserServiceIml3(UserDao userDao) {
super();
this.userDao = userDao;
}
在XML中bean定义如下:
- <bean id="user1" class="com.test.service.UserServiceIml1"/>
- <bean id="user2" class="com.test.service.UserServiceIml2" />
- <bean id="user3" class="com.test.service.UserServiceIml3"/>
<bean id="user1" class="com.test.service.UserServiceIml1"/>
<bean id="user2" class="com.test.service.UserServiceIml2" />
<bean id="user3" class="com.test.service.UserServiceIml3"/>
以上的注入是我们自己定义的接口,当然也可以注入spring核心的一些接口,如ApplicationContext,如下:
- @Autowired
- private ApplicationContext context;
@Autowired
private ApplicationContext context;
另外@Resource是JSR-250的注解,其含义和@Autowired 相同,但是有限制,要使其生效,需要在bean定义文件中声明相应的beanpostProcessor 见下:
- //可以用在字段和只有一个参数的set方法上,含义同等@Autowired
- @Resource
- private UserDao userDao;
//可以用在字段和只有一个参数的set方法上,含义同等@Autowired
@Resource
private UserDao userDao;
- <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/
另有JSR-330注解 @Inject 和 @Autowired的 作用基本一样,这里略过不提。
@Qualifier
@Autowired使用byType进行依赖的注入,可能会有多个匹配者(如我们有在Spring容器中有两个userDao的bean),那么这个时候就会抛出异常,因此我们需要更加细粒度的进行控制,这就是@Qualifier 登场的地方。@Qualifier 可以用到字段上,方法参数上,来从“名字”上对aotowired的候选bean进行限制。一般情况下,可以直接使用bean的name来作为@Qualifier的值来限制注入指定的bean. 当然也可以在xml中使用<Qualifier> 标签,这么做的好处是Qualifier 的值可以不是唯一的。
假如我们有两个UserDao,分别是userDao 和 userDao1,那么我们需要改以上的配置如下:
- //标注在构造函数上
- @Autowired
- public UserServiceIml3( @Qualifier("userDao1")
- UserDao userDao) {
- super();
- this.userDao = userDao;
- }
//标注在构造函数上
@Autowired
public UserServiceIml3( @Qualifier("userDao1")
UserDao userDao) {
super();
this.userDao = userDao;
}
- //标注在字段上。
- @Autowired
- @Qualifier("userDao")
- private UserDao userDao;
//标注在字段上。
@Autowired
@Qualifier("userDao")
private UserDao userDao;
其他剩下的略。
也可以使用标签定义qualifier :
- <bean id="userDao" class="com.test.dao.UserDaoImp">
- <qualifier value="main"/>
- </bean>
<bean id="userDao" class="com.test.dao.UserDaoImp">
<qualifier value="main"/>
</bean>
自定义@Qualifier
我们可以自定义注解,只要使用@Qualifier标注即可。如下:
- @Target({ElementType.FIELD,ElementType.PARAMETER})
- @Retention(RetentionPolicy.RUNTIME)
- @Qualifier
- public @interface MyQualify {
- String value();
- }
@Target({ElementType.FIELD,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MyQualify {
String value();
}
然后我们就可以使使用我们自定义的注解,来实现和@Qualifier相同的功能。在代码中和xml中的使用方式依次如下:
- @Autowired
- @MyQualify("userMy")
- private UserDao userDao;
@Autowired
@MyQualify("userMy")
private UserDao userDao;
- <bean id="userDao1" class="com.test.dao.UserDaoImp">
- <qualifier type="com.test.service.Myqualify" value="userMy"/>
- </bean>
<bean id="userDao1" class="com.test.dao.UserDaoImp">
<qualifier type="com.test.service.Myqualify" value="userMy"/>
</bean>
@value
用来自动装配基本类型(如int 等),可以和springEL 配合使用,也可以注入properties属性文件和常量值。
如下所示注入properties文件定义的值或者常量:
- package com.test.service;
- import org.springframework.beans.factory.annotation.Value;
- public class TestValue {
- @Value("${a}")
- private int a ;
- @Value("${b}")
- private String b;
- @Value("${c}")
- private boolean c;
- private double d;
- /**
- * properties的定义
- */
- @Value("${d}")
- public void setD(double d) {
- this.d = d;
- }
- /**
- * 注入常量
- */
- @Value(" i am const")
- private String e;
- @Override
- public String toString() {
- return "TestValue [a=" + a + ", b=" + b + ", c=" + c + ", d=" + d
- + ", e=" + e + "]";
- }
- }
package com.test.service;
import org.springframework.beans.factory.annotation.Value;
public class TestValue {
@Value("${a}")
private int a ;
@Value("${b}")
private String b;
@Value("${c}")
private boolean c;
private double d;
/**
* properties的定义
*/
@Value("${d}")
public void setD(double d) {
this.d = d;
}
/**
* 注入常量
*/
@Value(" i am const")
private String e;
@Override
public String toString() {
return "TestValue [a=" + a + ", b=" + b + ", c=" + c + ", d=" + d
+ ", e=" + e + "]";
}
}
testvalue.properties的值如下:
a=11 b=11 c=true d=1.33 |
最后需要在xml文件中加入对properties文件的读取,不要加入相应的命名空间,如下:
- <context:property-placeholder location="classpath:/com/test/testvalue.properties"/>
<context:property-placeholder location="classpath:/com/test/testvalue.properties"/>
总结
以上较详细的说明了下Spring 支持的依赖级别的注解的使用方法,主要介绍了@Autowired和@qualifier ,简单的介绍了其他如 @Resource 。对于JSR-330 @Inject 则略过,其实它和@Autowired的作用一样,但是没有其功能强大。@Required 没有提。
最后注意,Spring使用BeanPostProcessor来处理@Autowired等注解,所以在自定义的的BeanPostProcessor中不能使用这些它,必须在xml文件中配置。