1 @Autowired 干嘛的?
用来执行依赖注入。每当一个Spring管理的bean发现有该注解时,会直接注入相应的另一个Spring管理的bean。
1.1 不同地方放置有不同作用
-
属性
Spring将通过扫描自定义的package或通过在配置文件中直接查找bean
- 方法
使用 @Autowired 注解的每个方法都要用到依赖注入。但注意,签名中呈现的所有对象都必须是Spring所管理的bean。
如果你有一个方法,比如setTest(Article article, NoSpringArticle noSpringArt),其中只有一个参数 (Article article)是由Spring管理,那么就将抛org.springframework.beans.factory.BeanCreationException异常。这是由于Spring容器里并没有指定的一个或多个参数所指向的bean,所以也就无法解析它们。
1.2 bean的注入方式
-
名称
bean解析是通过bean名称
-
类型
解析基于bean的类型
1.3 @Qualifier 协作
如下相同类型的bean
<bean name="article1" class="com.sss.Article">
<property name="text" value="Content of the 1st Article" />
</bean>
<bean name="article2" class="com.sss.Article">
<property name="text" value="Content of the 2nd Article" />
</bean>
假如只是一个简单的@Autowired,Spring根本不知道你要注入哪个bean。这就需要
@Qualifier(value = "beanName")
譬如,要从
com.javaedge.Article
类型的bean中区分article1、article2:
@Qualifier(value="article1")
@Autowired
private Article firstArticle;
@Qualifier(value="article2")
@Autowired
private Article secondArticle;
2 优雅地使用@Autowired
启动自动注入
<context:annotation-config />
放在应用程序上下文配置。可以使在遇到@Autowired注解时启用依赖注入
- bean
// beans first
public class Comment {
private String content;
public void setContent(String content) {
this.content = content;
}
public String getContent() {
return this.content;
}
}
// sample controller
@Controller
public class TestController {
@Qualifier(value="comment1")
@Autowired
private Comment firstComment;
@Qualifier(value="comment2")
@Autowired
private Comment secondComment;
@RequestMapping(value = "/test", method = RequestMethod.GET)
public String test() {
System.out.println("1st comment text: "+firstComment.getText());
System.out.println("2nd comment text: "+secondComment.getText());
return "test";
}
}
// no-Spring managed class
public class TestNoSpring {
@Autowired
private Comment comment;
public void testComment(String content) {
if (comment == null) {
System.out.println("Comment's instance wasn't autowired because this class is not Spring-managed bean");
} else {
comment.setContent(content);
System.out.println("Comment's content: "+comment.getContent());
}
}
}
- 配置
<bean name="comment1" class="com.sss.exchanger.Comment">
<property name="content" value="Content of the 1st comment" />
</bean>
<bean name="comment2" class="com.sss.exchanger.Comment">
<property name="content" value="Content of the 2nd comment" />
</bean>
自测发现TestController的注解字段正确地自动注入,而TestNoSpring的注解字段并没有注入进去
1st comment text: Content of the 1st comment
2nd comment text: Content of the 2nd comment
Comment's instance wasn't autowired because this class is not Spring-managed bean
因为TestNoSpring类不由Spring所管理,这就是为什么Spring不能注入Comment实例的依赖。
3 @Autowired注解背后的秘密
应用程序上下文具有入口点,在Web应用程序中,是
dispatcherservlet
。容器(也就是该上下文)会在它那里被启动并且所有的bean都会被注入。
看
<context:annotation-config />
的定义
<xsd:element name="annotation-config">
<xsd:annotation>
<xsd:documentation><![CDATA[
Activates various annotations to be detected in bean classes: Spring's @Required and
@Autowired, as well as JSR 250's @PostConstruct, @PreDestroy and @Resource (if available),
JAX-WS's @WebServiceRef (if available), EJB 3's @EJB (if available), and JPA's
@PersistenceContext and @PersistenceUnit (if available). Alternatively, you may
choose to activate the individual BeanPostProcessors for those annotations.
Note: This tag does not activate processing of Spring's @Transactional or EJB 3's
@TransactionAttribute annotation. Consider the use of the <tx:annotation-driven>
tag for that purpose.
See javadoc for org.springframework.context.annotation.AnnotationConfigApplicationContext
for information on code-based alternatives to bootstrapping annotation-driven support.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
类内部的注解,如@Autowired、@Value、@Required、@Resource以及Web Serivce相关的注解,是容器对Bean对象实例化和依赖注入时,通过容器中注册的Bean后置处理器处理这些注解的
所以配置了上面这个配置(<context:component-scan>假如有配置这个,那么就可以省略<context:annotation-config />)后,将隐式地向Spring容器注册AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor以及这4个专门用于处理注解的Bean后置处理器。
当 Spring 容器启动时,AutowiredAnnotationBeanPostProcessor 将扫描 Spring 容器中所有 Bean
当发现 Bean 中拥有@Autowired 注解时就找到和其匹配(默认按类型匹配)的 Bean
并注入到对应的地方中去。