Spring Bean的生命周期

前言

本文从源码(SpringBoot 2.3.0版本)入手,学习教材上所说的Bean的生命周期的4个阶段:

  1. Bean定义
  2. Bean初始化
  3. Bean的生存期
  4. Bean的销毁

其中,Bean初始化阶段涉及的内容较多,如依赖注入,BeanPostProcessor、Aware接口的调用,比较复杂,这里先给个结论。

Bean初始化过程中的生命周期:

  1. 调用InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
  2. Bean实例化(Instantiation)
  3. 调用InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
  4. 完成Bean的依赖注入,如HelloController依赖注入HelloServiceImpl,注入HelloService时会触发HelloService Bean的定义、初始化,因此这是一个递归过程
  5. 调用BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
  6. 调用每个BeanPostProcessor.postProcessBeforeInitialization(),当BeanPostProcessor=ApplicationContextAwareProcessor时,调用ApplicationContextAware.setApplicationContext()
  7. 调用InitializingBean.afterPropertiesSet()
  8. 调用@Bean的init-method方法
  9. 调用每个BeanPostProcessor.postProcessAfterInitialization()

Bean定义

在SpringBoot启动时,根据@ComponentScan指定的包路径(默认是当前包及其子包)扫描,把Bean的定义保存到IoC容器中。

SpringBoot Web应用使用的IoC容器为AnnotationConfigServletWebServerApplicationContext,这个容器包含一个属性:DefaultListableBeanFactory。DefaultListableBeanFactoryBeanFactory的实现类之一,它的作用就是保存bean定义和实例化bean。

在启动类SpringApplication.run()方法中,先确定使用的IoC容器为AnnotationConfigServletWebServerApplicationContext,然后调用此容器的refresh()方法,对DefaultListableBeanFactory进行配置,将Bean定义添加到DefaultListableBeanFactorybeanDefinitionMap中。

下面是主要的一些源码展示,这些方法间的调用链可以debug查看。

SpringApplication.run()方法:

1
2
3
4
5
6
7
8
9
10
11
public ConfigurableApplicationContext run(String... args) {
// ...
// 指定IoC容器为AnnotationConfigServletWebServerApplicationContext
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 刷新容器,调用了AnnotationConfigServletWebServerApplicationContext.refresh()方法
refreshContext(context);
// ..
}

ClassPathBeanDefinitionScanner.doScan()方法:

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
protected Set<BeanDefinitionHolder> doScan(String... basePackages) { // basePackages=启动类所在包
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
Set<BeanDefinition> candidates = findCandidateComponents(basePackage); // 所有Bean类的定义,如HelloController、HelloServiceImpl
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry); // 把Bean的定义添加到this.registry=DefaultListableBeanFactory中
}
}
}
return beanDefinitions;
}

DefaultListableBeanFactory部分源码:

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
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

/** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
// ...
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition); //添加Bean定义到beanDefinitionMap
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition); //添加Bean定义到beanDefinitionMap
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
// ...
}

到这一步,IoC容器中只有Bean的定义,还没有Bean的实例化对象。

Bean初始化

概述

Bean的初始化阶段的主要工作,就是实例化Bean再初始化Bean,初始化过程中就包含依赖注入。

默认配置的、单例且非懒加载的Bean,会在Bean定义步骤完成后立即初始化。

入口在IoC容器基类AbstractApplicationContext.finishBeanFactoryInitialization()方法:

1
2
3
4
5
6
// 初始化单例且非懒加载的bean,beanFactory=DefaultListableBeanFactory
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// ...
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}

主要工作的是AbstractAutowireCapableBeanFactory.doCreateBean()方法,这个类是DefaultListableBeanFactory的基类。

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
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();
// ...

// Initialize the bean instance.
Object exposedObject = bean;
try {
// 下面两行都是bean的初始化
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
// ...
return exposedObject;
}

下面介绍Bean初始化阶段的详细过程。

Bean实例化(Instantiation)

AbstractAutowireCapableBeanFactory.doCreateBean()方法中,createBeanInstance()方法负责Bean的实例化,实例化后的bean对象的属性还是空的。

1
2
3
4
5
6
7
8
9
10
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// ...
if (instanceWrapper == null) {
// 用bean的构造器创建bean对象,放在instanceWrapper内,此时bean对象的属性还是空的
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
// ...
}

Bean初始化(Initialization)

AbstractAutowireCapableBeanFactory.doCreateBean()方法中,populateBean()方法和initializeBean()方法完成Bean的属性赋值(包括依赖注入),和Bean的一些扩展接口的调用。

1
2
3
4
5
6
7
8
9
10
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// ...
try {
// 下面两行都是bean的初始化
populateBean(beanName, mbd, instanceWrapper); // 属性赋值,包括依赖注入
exposedObject = initializeBean(beanName, exposedObject, mbd);// 调用Bean的一些扩展接口,如BeanPostProcessor接口和Aware接口
}
// ...
}

populateBean()方法中完成依赖注入,如把personServiceImpl注入到personController中。

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
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// ...
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 稍微提一下,这里的autowired是@Bean注解的autowired属性值,不是bean的依赖属性上的@Autowired注解
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
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;
}
// ...
for (BeanPostProcessor bp : getBeanPostProcessors()) {
// InstantiationAwareBeanPostProcessor接口是BeanPostProcessor接口的子类,下面会介绍
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;

// 当bp=AutowiredAnnotationBeanPostProcessor时,这步会注入bean的依赖,如把personServiceImpl注入到personController中
// 在初始化personServiceImpl这个bean时,会递归调用到上面的doCreateBean()方法,且会递归把personMapper注入到personServiceImpl中
// 因此整个注入是一个递归调用的过程
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) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}

以上大致介绍了Bean的初始化阶段的主要工作,即实例化Bean再依赖注入。但在这个阶段,还涉及到BeanPostProcessor接口和*Aware接口的调用。下面介绍这两类接口的作用和调用时机。

调用扩展接口

BeanPostProcessor接口

BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口。接口声明如下:

1
2
3
4
5
6
7
8
9
10
11
public interface BeanPostProcessor {
/**
* 在Bean的 InitializingBean.afterPropertiesSet()方法或@Bean(init-method)属性定义的方法 执行前被调用
*/
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

/**
* 在Bean的 InitializingBean.afterPropertiesSet()方法或@Bean(init-method)属性定义的方法 执行后被调用
*/
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

实现了BeanPostProcessor接口的类,被扫描进IoC容器后,在所有Bean的初始化前后都会被调用,即它对所有Bean都生效,有点像AOP。它有个子接口InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor接口

InstantiationAwareBeanPostProcessor接口继承自BeanPostProcessor接口,它不仅继承了BeanPostProcessor接口会在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
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

// bean实例化前调用
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}

// bean实例化后调用
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}

@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return null;
}

@Deprecated
@Nullable
default PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
}

Aware接口

Aware类型的接口的作用就是让我们能够拿到Spring容器中的一些资源,Aware之前的名字就是可以拿到什么资源,例如BeanNameAware可以拿到BeanName,以此类推。
比较常见的Aware接口有BeanNameAware、BeanFactoryAware、ApplicationContextAware。

ApplicationContextAware接口

ApplicationContextAware接口可以用来获取ApplicationContext,即IoC容器。我们已知ApplicationContext包含BeanFactory接口的getBean()方法,因此我们在服务中可以借助它直接获取Bean。

1
2
3
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}

我们在项目中,经常遇到要随时获取Bean的情况,这时就可以写一个工具类解决:ApplicationContextUtil。这个工具类就是使用了ApplicationContextAware接口的特性。

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
@Component
public class ApplicationContextUtil implements ApplicationContextAware {

private static ApplicationContext context;

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}

/**
* 通过name获取 Bean.
*/
public static Object getBean(String name) {
return context.getBean(name);
}

/**
* 通过class获取Bean.
*/
public static <T> T getBean(Class<T> clazz) {
return context.getBean(clazz);
}

/**
* 通过name,以及Clazz返回指定的Bean
*/
public static <T> T getBean(String name, Class<T> clazz) {
return context.getBean(name, clazz);
}
}

那么,我们定义的这个Bean,ApplicationContextUtil,它的setApplicationContext()方法是在何时被调用的?答案在下面“调用时机”一节中。

调用时机

BeanFactory注册BeanPostProcessor接口

在AnnotationConfigServletWebServerApplicationContext.refresh()方法中(在Bean定义阶段中有提到),会给要使用的BeanFactory=DefaultListableBeanFactory注册BeanPostProcessor接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
/*省略其他代码*/
// Prepare the bean factory for use in this context.
// 这里会添加几个指定的BeanPostProcessor
prepareBeanFactory(beanFactory);
try {
// Register bean processors that intercept bean creation.
// 这里会注册自定义的BeanPostProcessor
registerBeanPostProcessors(beanFactory);
}
}
}

调用BeanPostProcessor和Aware接口方法

在Bean初始化阶段的initializeBean()方法中,顺序调用了BeanPostProcessor和Aware接口方法。

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 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 {
invokeAwareMethods(beanName, bean); // 调用Aware接口方法,见下方
}

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 执行每个BeanPostProcessor的postProcessBeforeInitialization()方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

try {
invokeInitMethods(beanName, wrappedBean, mbd);// 调用afterPropertiesSet()和init-method方法,见下方
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 执行每个BeanPostProcessor的postProcessAfterInitialization()方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

return wrappedBean;
}

// 判断bean是否实现了BeanNameAware等接口的方法,若实现就调用
// ApplicationContextAware接口的调用不在这里,后面介绍
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}

// 判断bean是否实现了InitializingBean接口,若实现就调用afterPropertiesSet(),然后反射调用init-method()方法
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {

boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}

if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}

从源码中可以看到,每初始化一个Bean。就会遍历调用所有的BeanPostProcessor接口方法,即BeanPostProcessor接口方法对所有Bean都有效。而Aware接口是由Bean自己实现的,初始化某个Bean时,会调用Bean自己的Aware接口方法,因此Aware接口方法只针对一个Bean有效。

ApplicationContextAware接口的调用

ApplicationContextAware接口的调用点如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 {
invokeAwareMethods(beanName, bean); // 这里没有调用ApplicationContextAware
}

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 这里调用了ApplicationContextAware
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
// ...
}

在applyBeanPostProcessorsBeforeInitialization()方法中,会遍历执行BeanFactory的所有BeanPostProcessor.postProcessBeforeInitialization()方法,当遍历到ApplicationContextAwareProcessor.postProcessBeforeInitialization()方法时,它的源码如下:

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
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// ...
if (acc != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareInterfaces(bean);
return null;
}, acc);
}
else {
invokeAwareInterfaces(bean);
}

return bean;
}

private void invokeAwareInterfaces(Object bean) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); // 当bean实现了ApplicationContextAware,调用setApplicationContext()方法
}
}

至于这个ApplicationContextAwareProcessor是何时添加到BeanFactory的,答案在上面介绍的“BeanFactory注册BeanPostProcessor接口”的prepareBeanFactory()方法中。

1
2
3
4
5
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// ...
}

InstantiationAwareBeanPostProcessor接口的调用

介绍InstantiationAwareBeanPostProcessor接口时,提到它扩展的两个方法:postProcessBeforeInstantiation()、postProcessAfterInstantiation(),分别在Bean实例化前后调用。具体的调用点如下。

postProcessBeforeInstantiation()的调用点在AbstractAutowireCapableBeanFactory.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
36
37
38
39
40
41
42
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// ...
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 这里是调用点,见下方
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// ...
try {
// 可以看到,它的调用点在doCreateBean()之前,说明此时还没有实例化bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
// ...
}

// hasInstantiationAwareBeanPostProcessors=true时,执行postProcessBeforeInstantiation()方法
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}

postProcessAfterInstantiation()的调用点,是我们熟悉的populateBean()方法:

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
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}

// 在populateBean()方法最前,此时bean已实例化但还未依赖注入
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
// ...
}

Bean初始化阶段总结

在Bean初始化过程中的生命周期是这样的:

  1. BeanFactory注册BeanPostProcessor接口
  2. 调用InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
  3. createBeanInstance()进行Bean实例化
  4. populateBean()
    1. 调用InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
    2. 调用AutowiredAnnotationBeanPostProcessor.postProcessProperties(),完成依赖注入,是一个递归过程
  5. initializeBean()
    1. 调用BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
    2. 调用每个BeanPostProcessor.postProcessBeforeInitialization(),当BeanPostProcessor=ApplicationContextAwareProcessor时,调用ApplicationContextAware.setApplicationContext()
    3. 调用InitializingBean.afterPropertiesSet()
    4. 调用@Bean的init-method方法
    5. 调用每个BeanPostProcessor.postProcessAfterInitialization()

可能有人会问,在Bean定义阶段使用的DefaultListableBeanFactory的成员变量beanDefinitionMap在Bean初始化阶段怎么没有出现?其实是出现了的。回顾doCreateBean()方法:

1
2
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {...}

第二个形参RootBeanDefinition mbd是从该方法的上上一层方法AbstractBeanFactory.doGetBean()传进来的:
【调用链是 AbstractBeanFactory.doGetBean() -> AbstractAutowireCapableBeanFactory.createBean() -> AbstractAutowireCapableBeanFactory.doCreateBean()

1
2
3
4
5
6
7
8
9
10
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
createBean(beanName, mbd, args);

// 其余略...
}

getMergedLocalBeanDefinition()方法中,调用DefaultListableBeanFactory.getBeanDefinition(),从beanDefinitionMap中获得Bean定义信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null && !mbd.stale) {
return mbd;
}
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}

public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
BeanDefinition bd = this.beanDefinitionMap.get(beanName);
if (bd == null) {
if (logger.isTraceEnabled()) {
logger.trace("No bean named '" + beanName + "' found in " + this);
}
throw new NoSuchBeanDefinitionException(beanName);
}
return bd;
}

Bean的生存期

Bean的生存期就是SpringBoot程序启动后,我们使用Bean的过程,这里不介绍了。

Bean的销毁

当 IoC 容器关闭时会对 Bean 进行销毁,此时会调用 Bean 的自定义销毁方法。

注意:销毁方法内只做 Bean 销毁前要做的事,比如调用下 Bean 内成员的销毁方法,Bean 资源的释放还是由 JVM 完成。

容器启动时记录定义了销毁方法的Bean

有以下3种方式来自定义 Bean 的销毁方法:

  1. 实现 DisposableBean 接口
  2. @Bean(destroyMethod=”xxx”)
  3. @PreDestroy

这3种方法的代码示例:

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
// 1
public class Person2 implements DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("===================destroy person2 bean");
}
}

// 2
public class Person {
public void destroy(){
System.out.println("===================destroy person bean");
}
}

// 3
public class Person3 {
@PreDestroy
public void destroy() throws Exception {
System.out.println("===================destroy person3 bean");
}
}

// 它们注册为Bean的代码
@Configuration
public class BeanConfig {
@Bean(destroyMethod = "destroy")
Person person() {
return new Person();
}

@Bean
Person2 person2() {
return new Person2();
}

@Bean
Person3 person3() {
return new Person3();
}
}

IoC容器启动时,在AbstractAutowireCapableBeanFactory.doCreateBean()方法中,完成当前 Bean 的初始化后(即调用完 initializeBean 方法后),会调用父类的registerDisposableBeanIfNecessary方法,判断当前 Bean 是否含自定义销毁方法,若有则记录在容器成员Map<String, Object> disposableBeans中。
这部分源码如下:

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
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// ...

// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd); // 调用父类方法
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = System.getSecurityManager() != null ? this.getAccessControlContext() : null;
// 当前Bean的作用域不是原型 且 this.requiresDestruction() = true
// 所以,作用域为原型的Bean,IoC容器不负责销毁
if (!mbd.isPrototype() && this.requiresDestruction(bean, mbd)) {
if (mbd.isSingleton()) {
// 单例Bean被包装成DisposableBeanAdapter添加到disposableBeans Map中
this.registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, mbd, this.getBeanPostProcessors(), acc));
} else {
Scope scope = (Scope)this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}

scope.registerDestructionCallback(beanName, new DisposableBeanAdapter(bean, beanName, mbd, this.getBeanPostProcessors(), acc));
}
}
}

protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
return bean != null && (DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || this.hasDestructionAwareBeanPostProcessors() && DisposableBeanAdapter.hasApplicableProcessors(bean, this.getBeanPostProcessors()));
}

this.requiresDestruction() 方法就是用于判断一个 Bean 是否有自定义销毁方法,只要以下2个条件之一成立则返回 true:

  1. DisposableBeanAdapter.hasDestroyMethod() = true
    1. Bean 是否实现了 DisposableBean 或 AutoCloseable 接口;
    2. 若上条不符,那么是否指定 @Bean 注解的 destroyMethod 属性;
    3. 若上条不符,那么 Bean 类中是否有名为“close”或“shutdown”的方法。
  2. this.hasDestructionAwareBeanPostProcessors() && DisposableBeanAdapter.hasApplicableProcessors() = true
    容器中的 beanPostProcessorList 中有DestructionAwareBeanPostProcessor类型的 Bean,且它对当前 Bean 适用。

第二个条件中的 DestructionAwareBeanPostProcessor 接口继承自 BeanPostProcessor,扩展了2个方法:

1
2
3
4
5
6
public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {
// 调用bean自定义销毁方法前要做的事
void postProcessBeforeDestruction(Object var1, String var2) throws BeansException;
// 对形参中的bean是否有效【这个方法返回true,才会调用上一个方法
boolean requiresDestruction(Object var1);
}

那么容器中有 DestructionAwareBeanPostProcessor 类型的 Bean 吗?有!在容器 refresh 时,添加了一个ApplicationListenerDetectorBean,它只对 ApplicationListener Bean 适用;还有一个 CommonAnnotationBeanPostProcessor,它对使用了 @PreDestroy 注解的 Bean 适用。

所以,当 Bean 使用了3种方法中的任一种(也可以同时用)自定义销毁方法,this.requiresDestruction() 方法就会返回 true,这个 Bean 会被包装成DisposableBeanAdapter添加到容器的 disposableBeans Map 中。

容器关闭时调用Bean的销毁方法

IoC 容器关闭时会对 Bean 进行销毁,此时会通过容器中的 BeanFactory 调用 Bean 的自定义销毁方法。

DefaultSingletonBeanRegistry.destroySingletons()方法(DefaultSingletonBeanRegistry 是 DefaultListableBeanFactory 的间接基类):

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
public void destroySingletons() {
// ...

String[] disposableBeanNames;
synchronized(this.disposableBeans) {
disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
}

// 遍历disposableBeanNames,一个一个调用destroySingleton方法【相当于遍历disposableBeans Map
for(int i = disposableBeanNames.length - 1; i >= 0; --i) {
this.destroySingleton(disposableBeanNames[i]); // 见下方
}

// ...
}

public void destroySingleton(String beanName) {
this.removeSingleton(beanName);
DisposableBean disposableBean;
synchronized(this.disposableBeans) {
disposableBean = (DisposableBean)this.disposableBeans.remove(beanName);
}

this.destroyBean(beanName, disposableBean); // 见下方
}

protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
// Trigger destruction of dependent beans first...
Set<String> dependencies;
synchronized (this.dependentBeanMap) {
// Within full synchronization in order to guarantee a disconnected Set
dependencies = this.dependentBeanMap.remove(beanName);
}
if (dependencies != null) {
if (logger.isTraceEnabled()) {
logger.trace("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);
}
for (String dependentBeanName : dependencies) {
destroySingleton(dependentBeanName); // 销毁bean依赖的bean
}
}

// Actually destroy the bean now...
if (bean != null) {
try {
bean.destroy(); // 调用自定义销毁方法
}
catch (Throwable ex) {
if (logger.isWarnEnabled()) {
logger.warn("Destruction of bean with name '" + beanName + "' threw an exception", ex);
}
}
}
// ...
}

上面源码说明了销毁 Bean 的过程:遍历 disposableBeans Map,分别调用这些 Bean 的 destroy 方法完成销毁。从上一小节我们知道,disposableBeans Map 保存了所有含自定义销毁方法的 Bean,且这些 Bean 是被包装成 DisposableBeanAdapter 对象保存的,所以源码中调用bean.destroy()其实是调用DisposableBeanAdapter.destroy()

在看 DisposableBeanAdapter.destroy() 方法之前,先看一下当初 Bean 是怎么被包装成 DisposableBeanAdapter 的。DisposableBeanAdapter 构造方法源码:

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
public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition, List<BeanPostProcessor> postProcessors, AccessControlContext acc) {
Assert.notNull(bean, "Disposable bean must not be null");
this.bean = bean;
this.beanName = beanName;
// 1
this.invokeDisposableBean = this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy");
this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
this.acc = acc;

// 2
String destroyMethodName = this.inferDestroyMethodIfNecessary(bean, beanDefinition);

// 3
if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
!beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
this.destroyMethodName = destroyMethodName;
this.destroyMethod = this.determineDestroyMethod();
if (this.destroyMethod == null) {
if (beanDefinition.isEnforceDestroyMethod()) {
throw new BeanDefinitionValidationException("Couldn't find a destroy method named '" + destroyMethodName + "' on bean with name '" + beanName + "'");
}
} else {
Class<?>[] paramTypes = this.destroyMethod.getParameterTypes();
if (paramTypes.length > 1) {
throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" + beanName + "' has more than one parameter - not supported as destroy method");
}

if (paramTypes.length == 1 && Boolean.TYPE != paramTypes[0]) {
throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" + beanName + "' has a non-boolean parameter - not supported as destroy method");
}
}
}

// 4
this.beanPostProcessors = this.filterPostProcessors(postProcessors, bean);
}

解释上面源码中标注的点:

  1. 判断条件中beanDefinition.isExternallyManagedDestroyMethod("destroy")当使用了 @PreDestroy 注解且这个注解标注的方法名为”destroy”时为 true。这一行代码含义是,当 Bean 实现了 DisposableBean 接口且 destroy 方法未标注 @PreDestroy 时,this.invokeDisposableBean = true
  2. this.inferDestroyMethodIfNecessary()方法中,若定义了@Bean 的 destroyMethod 属性则直接返回;若实现了 DisposableBean 接口则返回 null;若有名为”close”方法或”shutdown”方法,则返回”close”或”shutdown”,否则返回 null
  3. 这里if条件成立的场景是:(destroyMethodName != null) 且 (未实现 DisposableBean 或 实现了 DisposableBean 但 destroyMethodName!=”destory”) 且 destroyMethodName 方法未标注 @PreDestroy 注解
  4. 从容器中所有 beanPostProcessor 中筛选对当前 Bean 有效的

从上面这几点还可以看出:

  1. 若 @Bean(destroyMethod=”xxx”) 和 DisposableBean 同时用,且前者定义的销毁方法与后者不同(后者只能是 destory 方法),则这两者分别定义的销毁方法都会被调用
  2. 若 @Bean(destroyMethod=”xxx”) 和 @PreDestroy 同时用,且前者定义的销毁方法与后者不同,则这两者分别定义的销毁方法都会被调用
  3. 若 DisposableBean 和 @PreDestroy 同时用,且前者定义的销毁方法(只能是 destory 方法)与后者不同,则这两者分别定义的销毁方法都会被调用
  4. 若只使用了 @Bean 但未定义 destroyMethod 属性,则会自动取方法名为”close”或”shutdown”的方法作为销毁方法

这里使用了“适配器模式”,DisposableBeanAdapter 适配了自定义销毁方法的3种方式。

倒回来看 DisposableBeanAdapter.destroy() 源码:

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
@Override // DisposableBeanAdapter本身也实现了DisposableBean接口
public void destroy() {

// 遍历调用所有适合这个bean的DestructionAwareBeanPostProcessor,执行销毁前要做的事
// 如果是用@PreDestroy注解,那么这里会通过CommonAnnotationBeanPostProcessor调用到注解标注的方法
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}

// 如果是实现了DisposableBean,则调用destroy方法
if (this.invokeDisposableBean) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
}
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
((DisposableBean) bean).destroy();
return null;
}
}, acc);
}
else {
((DisposableBean) bean).destroy();
}
}
catch (Throwable ex) {
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex);
}
else {
logger.warn(msg + ": " + ex);
}
}
}

// 若使用@Bean(destroyMethod="xxx"),调用指定方法
if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
Method methodToCall = determineDestroyMethod();
if (methodToCall != null) {
invokeCustomDestroyMethod(methodToCall);
}
}
}

综上,无论使用哪一种方式自定义销毁方法,这个 Bean 会在容器启动时包装成 DisposableBeanAdapter。容器关闭时,调用 BeanFactory 方法:DefaultSingletonBeanRegistry.destroySingletons(),这个方法内再通过 DisposableBeanAdapter 执行自定义销毁方法。


这里简单介绍下容器关闭的原理。

容器关闭时执行的方法是:AbstractApplicationContext.doClose(),就是在这个方法内调用了 DefaultSingletonBeanRegistry.destroySingletons() 方法,那么它是怎么被调用的?

IoC 容器关闭有2种情况,一个是主动调用容器的 close 方法,像下面这样:

1
2
3
4
5
6
7
8
public class MysqlDemoApplication {

public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
System.out.println(context.getBean(HelloWorldController.class));
context.close();// IoC容器关闭,会调用AbstractApplicationContext.doClose()方法
}
}

但在一般项目中不会有这样的代码,所以第二种情况就是让 Spring 自动完成关闭容器的操作。Spring 怎么自己知道要关闭容器?

SpringApplication.refreshContext()方法源码(如下)中可以看到,程序启动时,SpringApplication 调用完容器的 refresh 方法后,紧接着调用了容器的registerShutdownHook方法。

1
2
3
4
5
6
7
8
9
private void refreshContext(ConfigurableApplicationContext context) {
this.refresh(context);
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
} catch (AccessControlException var3) {
}
}
}

registerShutdownHook 方法是接口 ConfigurableApplicationContext 定义的,由 AbstractApplicationContext(所有容器类的基类)实现。实现代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
public void registerShutdownHook() {
if (this.shutdownHook == null) {
this.shutdownHook = new Thread() {
public void run() {
synchronized(AbstractApplicationContext.this.startupShutdownMonitor) {
AbstractApplicationContext.this.doClose();
}
}
};
Runtime.getRuntime().addShutdownHook(this.shutdownHook);
}

}

这个方法的最后调用了 JDK 的一个方法:Runtime.addShutDownHook(Thread hook) ,作用是:注册一个 JVM 关闭的钩子方法。此处可以看出,这个“钩子方法”是一个线程,线程内调用了 AbstractApplicationContext.doClose() 方法 ,这个线程会在JVM 正常关闭时被执行。

什么是钩子方法?

钩子方法是设计模式中的模板模式里用到的,它是由抽象类声明并且实现,实现内容一般是空的,子类可以选择是否扩展。钩子方法为你在实现某一个抽象类的时候提供了可选项,相当于预先提供了一个默认配置。

JVM正常关闭的条件是?

用”kill”命令而不是”kill -9”命令,在idea编辑器里点击”exit”按钮而不是”stop”按钮。