Spring源码分析 —— bean依赖注入

Spring bean的生命周期涉及的知识点太多而且比较复杂,很难在一篇文章中把Spring bean生命周期所有的方面都讲清楚。所以按照几条线来分别整理,最后再写一篇汇总的文章串联起来。

本文依然基于annotation注解配置的方式进行分析。

回顾一下我们说过Spring bean的生命周期主要大概有以下几个步骤:

  • 创建bean的实例
  • 给实例化出来的bean填充属性
  • 初始化bean
  • 通过IOC容器使用bean
  • 容器关闭时销毁bean

本文就对第二阶段bean的依赖注入(Dependency Injection)分以下几个问题来整理:

  • 什么是Spring容器和依赖注入?
  • 何时发生依赖注入?
  • Spring依赖注入的源码

什么是Spring容器和依赖注入?

上次我们说过,IOC是一种重要的设计理念,而Spring IOC又是基于这个理念在Spring framework实现的高级特性。Spring IOC具备以下两个特性:

  1. 准备Bean的整个生命周期需要的数据:在这一步中,Spring容器会定位配置文件,加载各种Class文件,并且将其解析成BeanDefinition(重要数据类型),这个BeanDefinition会贯穿Spring容器及Spring运行环境初始化的整个流程,是我们尤其要关注的数据基础;
  2. 管理整个Bean的生命周期:完成bean实例化、完成各个bean之间依赖关系注入(本文所分析)、完成bean的初始化及销毁。

依赖注入和属性注入的区别

依赖注入其实是属性注入的一种特殊情形,特殊之处就在于它要注入的是bean,而不是String、List、Array这种。

我们通过@Autowire标签来完成依赖注入。

何时发生依赖注入?

回看之前我们分析的bean实例化源码,可以看到一丝线索。

在AnnotationConfigApplicationContext初始化时,调用关键方法refresh():

1
2
3
4
5
6
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
// Spring容器初始化入口
refresh();
}

Spring初始化入口refresh(省略了部分代码,提升阅读体验):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();

// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);

try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);

// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);

...

// Instantiate all remaining (non-lazy-init) singletons.
// 在这里初始化所有非懒加载的bean!!!!
finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event.
finishRefresh();
}
}
}

点进去finishBeanFactoryInitialization(beanFactory)里头有个初始化non-lazy-init bean的函数preInstantiateSingletons(),具体逻辑如下:

  1. 对beanNames集合遍历获取每个BeanDefinition;
  2. 判断是否是懒加载的,如果不是则继续处理(non-lazy-init bean不做处理);
  3. 判断是否是factorybean如果不是则进行实例化并依赖注入。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@Override
public void preInstantiateSingletons() throws BeansException {
// 所有beanDefinition集合
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

// Trigger initialization of all non-lazy singleton beans...
// 触发所有非懒加载单例bean的初始化
for (String beanName : beanNames) {
// 获取beanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 判断是否是懒加载单例bean,如果是单例的并且不是懒加载的则在Spring 容器
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 判断是否是FactoryBean
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
} else {
// 如果是普通bean则进行初始化依赖注入,此getBean(beanName)接下来触发的逻辑跟
// context.getBean("beanName") 所触发的逻辑是一样的
getBean(beanName);
}
}
}
}

对于懒加载的bean,本质上就是手动去调用这个getBean(beanName)方法。所以在此我们找到了依赖注入的入口。

Spring依赖注入的源码

依赖注入实现的入口

getBean()是个空壳方法,里面直接调用doGetBean():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
...
// Create bean instance.
// 如果scope是单例,创建bean
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
// 创建bean实例
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
...
}

这个getSingleton()的第二个参数使用lambda表达式传入createBean()方法,真正创建bean实例的方法在这个createBean()方法里面。

createBean()中经过一系列预处理,最后调doCreateBean()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
//第一步 创建bean实例,还未进行属性填充和各种特性的初始化
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();

// Initialize the bean instance.
Object exposedObject = bean;
try {
// 第二步 进行属性填充(依赖注入)
populateBean(beanName, mbd, instanceWrapper);
// 第三步 执行bean的初始化方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
} catch (Throwable ex) {
// 抛相应异常
}

// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
} catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}

return exposedObject;
}

我们这里关注第二步进行依赖注入的代码populateBean(beanName, mbd, instanceWrapper):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 拿到所有的属性
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

int resolvedAutowireMode = mbd.getResolvedAutowireMode();
// 这里处理自动装配类型的,也就是autowire为byName还是byType
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}

// 查看后置处理器是否准备好,这里的后置处理器会通过其中一个子类InstantiationAwareBeanPostProcessors
// 来处理以@Autowire标签来注入的bean
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否需要依赖检查,分为4个等级:1. 不检查 - None;2. 检查object引用 - object;
// 3. 检查简单依赖 - simple;4. 全部检查 - all。
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
// 通过InstantiationAwareBeanPostProcessor接口的实现类来处理依赖注入
// 如果是注解方式,使用AutowiredAnnotationBeanPostProcessor
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 此处会进行对注解方式的注入!!!
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
if (pvs != null) {
// XML形式注入
applyPropertyValues(beanName, mbd, bw, pvs);
}
}

注解形式注入的源码

基于注解的方式我们关注PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName)这个方法调用。看一下AutowiredAnnotationBeanPostProcessor中的postProcessProperties()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 这里定义了把谁注入进哪里
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// 进行依赖注入
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}

InjectionMetadata这个类封装了依赖的bean信息private final Collection<InjectedElement> injectedElements;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
// 这里取的是Collection<InjectedElement> injectedElements这个集合
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
// 对集合中的元素进行注入
for (InjectedElement element : elementsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
// 此处通过反射完成注入method.invoke(target, getResourceToInject(target, beanName));
element.inject(target, beanName, pvs);
}
}
}

XML形式注入的源码

在populateBean()中最后面有通过XML形式注入的入口applyPropertyValues(beanName, mbd, bw, pvs);,这个方法主要做的事情是把属性转换为相应的类的属性类型,最终注入到bean中,主要分为三个步骤:

  • 判断是否完成转换;
  • 进行转换;
  • 注入到bean中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
MutablePropertyValues mpvs = null;
List<PropertyValue> original;

if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
// 判断是否完成转换
if (mpvs.isConverted()) {
// Shortcut: use the pre-converted values as-is.
try {
bw.setPropertyValues(mpvs);
return;
} catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
// 获取属性值的list
original = mpvs.getPropertyValueList();
} else {
original = Arrays.asList(pvs.getPropertyValues());
}

TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

// Create a deep copy, resolving any references for values.
List<PropertyValue> deepCopy = new ArrayList<>(original.size());
boolean resolveNecessary = false;
for (PropertyValue pv : original) {
if (pv.isConverted()) {
deepCopy.add(pv);
} else {
// 属性名
String propertyName = pv.getName();
Object originalValue = pv.getValue();
if (originalValue == AutowiredPropertyMarker.INSTANCE) {
Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
if (writeMethod == null) {
throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
}
originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
}
// 转换后的属性值,也就是对于1.Bean 2.Array 3.List 4.Set 5.Map 6.String等数据结构进行转换,重要!!!
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
Object convertedValue = resolvedValue;
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
// Possibly store converted value in merged bean definition,
// in order to avoid re-conversion for every created bean instance.
if (resolvedValue == originalValue) {
if (convertible) {
pv.setConvertedValue(convertedValue);
}
deepCopy.add(pv);
} else if (convertible && originalValue instanceof TypedStringValue &&
!((TypedStringValue) originalValue).isDynamic() &&
!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
} else {
resolveNecessary = true;
deepCopy.add(new PropertyValue(pv, convertedValue));
}
}
}
// 转换完成
if (mpvs != null && !resolveNecessary) {
mpvs.setConverted();
}

// Set our (possibly massaged) deep copy.
try {
// 进行属性注入,和注解方式的inject方法类似
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
} catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}

Spring中的循环依赖

Spring是支持循环依赖的,有人就要问循环是怎么解决的?其实这里有一个问题是:依赖注入的是对象,而不是bean;循环依赖是说bean A依赖对象B,bean B依赖对象A。所以上面我们分析的实例化对象之后,会首先将这个对象暴露出来,这就是解决循环依赖的一个关键点,具体的步骤是:

  1. A在推断完构造方法,并且通过反射new出来一个A对象之后,将A对象暴露出来,下一步要做依赖注入;
  2. 发现要依赖B,那么就开始B的bean初始化,并且将这个new出来的A对象放到一个set集合缓存当中;
  3. B在完成反射new对象之后,下一步也是要依赖注入,发现要依赖A;
  4. 因为依赖指的是依赖对象,而不是依赖bean,所以这时候B就可以去那个set中拿到A的实例,注入A的对象;
  5. 到这里为止,B完成了bean的初始化,并且放到单例池singletonMap中了,接下来A继续走流程;
  6. A在单例池中找到了B的bean,所以A也能注入B了;
  7. A也走完流程,完成bean初始化并且放到单例池中,至此循环依赖处理完成。

这里的代码读者可以自行追一下。

总结

依赖注入部分主要是以下几点:

  1. 依赖注入是bean生命周期的重要一环;
  2. 依赖注入是属性注入的一种,只不过注入的是bean类型;
  3. 何时发生依赖注入;
  4. 两种注入方式(注解方式和XML方式)的源码。