spring IOC 容器初始化bean的流程

这篇文章是我在实际项目中出现了循环依赖的问题后,发现对IOC容器初始化bean流程不清楚,导致在解决这个循环依赖问题用了很多时间,所以必须抽空对spring初始化bean流程进行理解。阅读了多篇文章和源码后,写下自己对bean初始化流程的理解。

首先容器初始化bean流程做了很多事情,比如完成对配置或注解文件的解析,允许并调用beanFactoryPostProcessors和BeanPostProcessor子类方法,国际化配置初始化,以及对bean实例化,属性注入,初始化完成bean等操作。

如果对springboot启动流程很熟悉的同学,也许会更清楚的知道初始化bean在springboot启动流程的什么位置上进行的。建议下先了解下springboot启动流程会再往下看会更加清楚明白。

SpringBootApplication.run()方法是启动流程中调用方法,在此方法中创建applicationContext后的refreshContext就是本文所要讲的对bean的初始化流程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
SpringApplication.java : 295
public ConfigurableApplicationContext run(String... args) {
//省略········
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//这里refresh就是将所有非懒加载的单例进行初始化
refreshContext(context);
afterRefresh(context, applicationArguments);
//省略·····
}
return context;
}

refresh()方法

这个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
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

AbstractApplicationContext.java : 515
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 刷新前准备工作,包括设置启动时间,是否激活标识位,初始化属性源(property source)配置
prepareRefresh();

// 创建beanFactory(过程是根据xml为每个bean生成BeanDefinition并注册到生成的beanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

//准备创建好的beanFactory(给beanFactory设置ClassLoader,设置SpEL表达式解析器,设置类型转化器【能将xml String类型转成相应对象】,
//增加内置ApplicationContextAwareProcessor对象,忽略各种Aware对象,注册各种内置的对账对象【BeanFactory,ApplicationContext】等,
//注册AOP相关的一些东西,注册环境相关的一些bean
prepareBeanFactory(beanFactory);

try {
// 模板方法,为容器某些子类扩展功能所用(工厂后处理器)这里可以参考BeanFactoryPostProcessor接口的postProcessBeanFactory方法
postProcessBeanFactory(beanFactory);

// 调用所有BeanFactoryPostProcessor注册为Bean
invokeBeanFactoryPostProcessors(beanFactory);

// 注册所有实现了BeanPostProcessor接口的Bean
registerBeanPostProcessors(beanFactory);

// 初始化MessageSource,和国际化相关
initMessageSource();

// 初始化容器事件传播器
initApplicationEventMulticaster();

// 调用容器子类某些特殊Bean的初始化,模板方法
onRefresh();

// 为事件传播器注册监听器
registerListeners();

// 初始化所有剩余的bean(普通bean)
finishBeanFactoryInitialization(beanFactory);

// 初始化容器的生命周期事件处理器,并发布容器的生命周期事件
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 销毁已创建的bean
destroyBeans();
// 重置`active`标志
cancelRefresh(ex);
throw ex;
}
finally {
//重置一些缓存
resetCommonCaches();
}
}
}

obtainFreshBeanFactory - 初始化Bean容器前的工作,初始化beanFactory类

明人不说暗话,将这个方法的作用先解释一下,带着这段话到源码中每一步分析会更加容易理解。该方法是读取配置文件或者注解文件解析出一个个bean的定义,注册到beanFactory中,这时候bean没有初始化,只是把配置信息提取出来。 beanName-> beanDefinition 的 map。BeanDefinition 中保存了我们的 Bean 信息,比如这个 Bean 指向的是哪个类、是否是单例的、是否懒加载、这个 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
AbstractRefreshableApplicationContext : 124
protected final void refreshBeanFactory() throws BeansException {
//判断是否已有beanFactory,如果有需要关闭并摧毁所有的bean。
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
//创建默认的beanFactory实例
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
//对beanFactory设置两个属性,是否允许覆盖,是否允许循环依赖
customizeBeanFactory(beanFactory);
//是读取所有配置文件或注解类解析出BeanDefinition后放在map中
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}

AbstractRefreshableApplicationContext : 224
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
//是否允许相同的bean覆盖
if (this.allowBeanDefinitionOverriding != null) {
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
//是否允许bean循环依赖
if (this.allowCircularReferences != null) {
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}

这里是bean的覆盖是指当初始化bean时发现factory中已经有相同id或name的bean了,此时是否允许覆盖之前的bean。

循环依赖也很好理解吧。A依赖B,B依赖C,C依赖A,那么A和C就是循环依赖。spring解决了属性注入的循环依赖,但如果注入依赖是通过构造函数注入的,这种spring解决不了。具体原因可以看下这篇文章 spring如何解决循环依赖

loadBeanDefinitions方法是将读取配置文件或注解类解析出bean类的定义,最常见的是通过指定路径下的xml和Annotation注解这两种方式。这里就不详细的详解下去了,因为这里面还有一大堆代码,为了不影响读者的耐心,只需要了解这个方法主要作用就可以了。 如果有兴趣详细了解可以看这篇文章,spring源码详解bean初始化

prepareBeanFactory方法,配置一些基础的类

配置一些基础的类,例如类的加载器,post-processors

postProcessBeanFactory和invokeBeanFactoryPostProcessors

允许并调用那些实现了beanFactoryPostProcessors的子类方法,提供了子类的扩展点,这一步指所有bean都被加载了,但没有初始化。这其中包括了springboot最重要的自动配置流程,这个也是springboot一大特性之一,是通过加载每个starter依赖jar包中的spring.factories加载指定的类。

registerBeanPostProcessors

注册那些beanPostProcessor的实现类,此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization,在初始化前后执行。注意这里只是注册并没有调用,后续会讲到何时会调用这两个方法

initMessageSource

初始化当前application的MessageSource,国际化相关的属性

finishBeanFactoryInitialization初始化所有singleten bean,除lazy-init外

这里会负责初始化所有非懒加载的单例bean,spring会在这个方法内对bean实例的创建,注入属性依赖,初始化bean完成。其中会包括如何解决循环依赖的问题以及前面提及到postProcessBeforeInitialization,postProcessAfterInitialization调用,还有init-method方法执行。

下面贴的代码是初始化bean的核心代码,至于如何跟踪到这个方法里的,有兴趣的读者可以在下面代码中打个断点,然后看debug的堆栈信息一步一步跟踪。

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
AbstractAutowireCapableBeanFactory : 546
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//第一步,创建bean的实例,通过构造函数创建实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}

// Allow post-processors to modify the merged bean definition.
//这里就是前面所说的post-processors会织入
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}

// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 这里是通过提前缓存单例解决循环依赖的问题
// 可以参考我另外一篇文章 spring如何解决循环依赖
// http://linyoga.com/2019/01/12/spring%E5%A6%82%E4%BD%95%E8%A7%A3%E5%86%B3%E5%BE%AA%E7%8E%AF%E4%BE%9D%E8%B5%96/
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

// Initialize the bean instance.
Object exposedObject = bean;
try {
//第二步,对bean进行属性依赖注入,
populateBean(beanName, mbd, instanceWrapper);
//第三步,对bean进行初始化完成,处理各种回调,比如上面所说的BeanPostProcessor实现类中的两个方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}

//省略。。

return exposedObject;
}

createBeanInstance根据构造函数实例化

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
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
// 确保已经加载了此 class
Class<?> beanClass = resolveBeanClass(mbd, beanName);

// 校验一下这个类的访问权限
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}

if (mbd.getFactoryMethodName() != null) {
// 采用工厂方法实例化,不熟悉这个概念的读者请看附录,注意,不是 FactoryBean
return instantiateUsingFactoryMethod(beanName, mbd, args);
}

// 如果不是第一次创建,比如第二次创建 prototype bean。
// 这种情况下,我们可以从第一次创建知道,采用无参构造函数,还是构造函数依赖注入 来完成实例化
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
// 构造函数依赖注入
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 无参构造函数
return instantiateBean(beanName, mbd);
}
}

// 判断是否采用有参构造函数
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 构造函数依赖注入
return autowireConstructor(beanName, mbd, ctors, args);
}

// 调用无参构造函数
return instantiateBean(beanName, mbd);
}

populateBean属性装配,注入依赖的bean

通过构造函数创建完bean的实例,以后要对实例中的属性进行设值并处理依赖关系,接下来pupulateBean对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
AbstractAutowireCapableBeanFactory : 1352
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
//省略。。。
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
//通过名字找到属性注入的bean
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable
// 通过类型找到属性注入的bean
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}

boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
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);
}
// 这里有个非常有用的 BeanPostProcessor 进到这里: AutowiredAnnotationBeanPostProcessor
// 对采用 @Autowired、@Value 注解的依赖进行设值,这里的内容也是非常丰富的,不过本文不会展开说了,感兴趣的读者请自行研究
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}

if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}

initializeBean初始化完成,处理回调方法

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 initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 如果 bean 实现了 BeanNameAware、BeanClassLoaderAware 或 BeanFactoryAware 接口,回调
invokeAwareMethods(beanName, bean);
}

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//处理Post—Processors中的BeforeInitialization回调方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

try {
//调用bean中定义的init-method方法
//或者实现InitializingBean接口中的afterPropertiesSet方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//处理Post—Processors中的AfterInitialization回调方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappdBean, beanName);
}
//返回已经初始化好的bean
return wrappedBean;
}

梳理一下,initializeBean方法会返回已经初始化好的bean,这中间会处理各种回调,为了加深方法流程的理解,创建一个类实践下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Configuration
public class BeanPostConfig implements BeanPostProcessor , InitializingBean {

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization");
return bean;
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization");
return bean;
}

@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet");
}
}

根据源码分析,控制台输出结果为

1
2
3
postProcessBeforeInitialization
afterPropertiesSet
postProcessAfterInitialization

到这里对bean的初始化已经完成了,概括下整个初始化流程,首先会解析配置文件或者注解类解析出beanDefinition注册到BeanFactory中,其次是对注册PostProcessor类,最后是初始化bean的流程,一个是创建 Bean 实例的 createBeanInstance 方法,一个是依赖注入的 populateBean 方法,还有就是回调方法 initializeBean。分为三个步骤,先根据构造函数创建实例,再根据属性进行依赖的注入,最后就是回调方法初始化bean。最后建议下读者启动项目debug下,跟踪下启动的流程,会对spring容器有一个更好的理解。

参考:

Spring IOC 容器源码分析

Spring容器IOC初始化过程


  Spring

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×