Spring源码分析 —— bean实例化原理

整理一下Spring bean的实例化相关内容。创建Spring bean实例是Spring bean生命周期的第一阶段。

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

bean实例化入口

Spring bean的生命周期主要有如下几个步骤:

  • 创建bean的实例
  • 给实例化出来的bean填充属性
  • 初始化bean
  • 通过IOC容器使用bean
  • 容器关闭时销毁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);
}
}
}
}

getBean()方法是实现bean初始化以及依赖注入的函数,本篇我们只关注bean的初始化。

对于lazy-init和non-lazy-init此时开始分叉。

初始化懒加载bean

上面preInstantiateSingletons()方法中看到如果不是懒加载的bean则执行初始化,实际上是Spring帮用户调用了getBean()方法来完成的。

所以在懒加载bean的情景中,preInstantiateSingletons()方法直接返回,我们在使用bean的时候手动去getBean(),也就是完成了后续的初始化过程,此谓“懒加载”。

1
2
3
4
5
public static void main(String[] args) {
AnnotationConfigApplicationContext ac =
new AnnotationConfigApplicationContext(AppConfig.class);
ac.getBean(AppConfig.class);
}

而对于非懒加载的bean,getBean()的时候会从缓存里头取,因为容器初始化阶段已经初始化了。

初始化普通的单例bean

寻找bean实例化入口

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;
}

在这里要注意区分bean实例化(第一步)和初始化(第三步)的区别:

  • 实例化是指完成对象创建,此时它只是一个java对象,还没有完成和Spring有关的集成,也就是没有完成各种PostProcessors的洗礼;
  • 初始化是指在完成实例化的同时,继而完成了各种与Spring容器集成等PostProcessors的处理,并且将其放入Spring的IOC容器中(本质上就是那个singletonMap)。

这里我们只关心第一步创建bean实例的流程:instanceWrapper = createBeanInstance(beanName, mbd, args);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName);

// 使用工厂方法进行实例化
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}

// Candidate constructors for autowiring?
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 使用带参构造函数初始化
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}

// No special handling: simply use no-arg constructor.
// 默认实例化方式 无参构造实例化
return instantiateBean(beanName, mbd);
}

这一步主要根据BeanDefinition里的元数据定义决定使用哪种实例化方法,主要有下面三种:

  • instantiateUsingFactoryMethod 工厂方法实例化的具体实现;
  • autowireConstructor 有参构造函数实例化的具体实现;
  • instantiateBean 默认实例化具体实现(无参构造函数)。

bean实例化策略

找到bean实例化入口后,我们来研究一下bean的实例化策略:

  • cglib;
  • 简单反射。

上面说到的两种实例化策略是根据BeanDefinition里的定义决定的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
getInstantiationStrategy().instantiate(mbd, beanName, parent),
getAccessControlContext());
}
else {
// 在这里选择一种策略进行实例化
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}

这里getInstantiationStrategy()会返回一种实例化策略,它们都是实现InstantiationStrategy接口的,该接口的实现类可以看到只有2种:

  • CglibSubclassingInstantiationStrategy:cglib策略;
  • SimpleInstantiationStrategy:简单反射策略。

然后真正调用实例化方法instantiate():

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
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
// methodOverride为空,也就是用户没有使用replace或者lookup的配置方法,采用简单反射的方式
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
// 决策使用哪种构造器
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(
(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
}
else {
constructorToUse = clazz.getDeclaredConstructor();
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
// 完成bean的实例化
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
// methodOverride不为空,采用cglib来创建
return instantiateWithMethodInjection(bd, beanName, owner);
}
}

总结

Bean实例化只是bean生命周期的一小部分,实际上只是bean初始化的一部分。

代码越读越薄。