微信搜索【程序员囧辉】,关注这个坚持分享技术干货的程序员。
目录
AutowiredAnnotationBeanPostProcessor 何时被注册到 BeanFactory?
AnnotationConfigUtils#registerAnnotationConfigProcessors
AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors
1.postProcessMergedBeanDefinition 方法介绍
AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
2.postProcessPropertyValues 方法介绍
AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues
代码块6:AutowiredFieldElement#inject
Spring IoC源码学习全系列
Spring IoC源码学习:ApplicationContext 刷新前的配置
Spring IoC源码学习:obtainFreshBeanFactory详解
Spring IoC源码学习:parseDefaultElement详解
Spring IoC源码学习:parseCustomElement详解
Spring IoC源码学习:context:component-scan 节点详解
Spring IoC源码学习:invokeBeanFactoryPostProcessors详解
Spring IoC源码学习:registerBeanPostProcessors详解
Spring IoC源码学习:finishBeanFactoryInitialization详解
Spring IoC源码学习:createBean详解(上)
Spring IoC源码学习:createBean详解(下)
Spring IoC源码学习:finishRefresh 详解
前言
在 Spring IoC:createBean 详解(上)中代码块4.5 和 Spring IoC:createBean详解(下)中代码块1、代码块4的 7.1.1 我们遗留了一个解析——@Autowire 注解的解析。之所以单独提出来,是因为在我现在接触的项目中,使用 @Autowire 注解的比例非常高,可以说基本用过 Spring 的同学都接触过这个注解,重要性不言而喻。因此,单独拿出来,较详细的介绍一下。
本文只会单独介绍 @Autowire 的部分内容,具体 @Autowire 注解的完整过程,需要结合 Spring IoC:createBean 详解(上)中代码块4.5 和 Spring IoC:createBean详解(下)中代码块1、代码块4的 7.1.1 去看。
如何使用
1.开启注解配置
<?xml version="1.0" encoding="UTF-8"?>
<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-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<!-- component-scan包含了annotation-config的效果 -->
<context:component-scan base-package="com.joonwhee.open.demo.service"/>
<context:annotation-config/>
</beans>
要使用 @Autowire 注解,可以通过 <context:component-scan /> 或 <context:annotation-config/> 来开启,其中前者是包含了后者的效果的,因此现在一般都使用 <context:component-scan /> 即可。
2.在代码中使用
@Service
public class ConstructorServiceImpl implements ConstructorService {
// 1.属性注入
@Autowired
private UserService userService;
private final DemoService demoService;
// 2.构造函数注入
@Autowired
public ConstructorServiceImpl(DemoService demoService) {
this.demoService = demoService;
}
}
该代码中使用了目前最常见的两种注入方式:1)属性注入;2)构造函数注入。
以我自己为例,我周围最常用的是:属性注入,但是 Spring 团队建议使用的方式是:构造函数注入,当你使用属性注入时,鼠标移到属性上的 @Autowire 就可以看到如下图的提示,并且可以通过快捷键将属性注入直接修改成构造函数注入。
构造函数的常见优点是:
- 保证依赖不可变(final 关键字)
- 保证依赖不为空(省去了检查)
- 以完全初始化的状态返回到客户端(调用)代码
- 避免了循环依赖
- 提升了代码的可复用性
构造函数的常见缺点是:
- 构造函数会有很多参数。
- 有些类是需要默认构造函数的,一旦使用构造函数注入,就无法使用默认构造函数。
-
这个类里面的有些方法并不需要用到这些依赖。
这些优点我看了下,个人觉得还好,只要不瞎用,其实使用属性注入并不会有什么问题。至于使用哪一种,就看个人喜好了。
继承结构
@Autowire 注解的功能实现都是由 AutowiredAnnotationBeanPostProcessor 实现,AutowiredAnnotationBeanPostProcessor 的继承关系如下图:
源码解析
AutowiredAnnotationBeanPostProcessor 何时被注册到 BeanFactory?
在 Spring IoC:context:component-scan节点详解 中的代码块17就有 AutowiredAnnotationBeanPostProcessor 被注册到 BeanFactory 的代码,如下:
AnnotationConfigUtils#registerAnnotationConfigProcessors
查看该方法的上下文,请参考:Spring IoC:context:component-scan节点详解 中的代码块17。
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
// 1.设置dependencyComparator属性
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
// 2.设置autowireCandidateResolver属性(设置自动注入候选对象的解析器,用于判断BeanDefinition是否为候选对象)
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);
// 3.注册内部管理的用于处理@Configuration注解的后置处理器的bean
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
// 3.1 registerPostProcessor: 注册BeanDefini