一、前言
上次我們在手把手教你解決回圈依賴,一步一步地來窺探出三級快取的奧秘中分析了Spring解決回圈依賴的方式,在第6節中的doCreateBean(AbstractAutowireCapableBeanFactory類中)其實已經隱約看到了Bean的生命周期的幾個階段,
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
//實體化bean
BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
//加入到三級快取中,getEarlyBeanReference會回傳單例工廠
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
Object exposedObject = bean;
//屬性賦值
populateBean(beanName, mbd, instanceWrapper);
//初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
if (earlySingletonExposure) {
//從二級快取中查找
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
//回傳二級快取中的bean,這里就有可能是代理后的物件
exposedObject = earlySingletonReference;
}
}
//銷毀前的準備,注冊待銷毀的Bean
registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
}
doCreateBean基本描述了Bean生命周期的大致框架——實體化、屬性賦值與初始化,當然Bean最后一步就是銷毀,
基本階段圖

請記住這張圖,也許你等會兒就不認識它了,
二、實體化與屬性賦值階段
當容器啟動時,會依據配置或注解掃描指定的包,將其中的類轉化為BeanDefinition,并集中在DefaultListableBeanFactory類的beanDefinitionMap變數里,
Spring中的BeanDdfinition,可以用來描述一個bean的作用域、是否懶加載、是否單例等,
容器啟動完成后,當我們試圖從容器獲取一個Bean時,第一步就是去實體化該Bean,說白了,就是需要呼叫構造方法,
注意到在呼叫doCreateBean之前,呼叫了resolveBeforeInstantiation方法,
1、resolveBeforeInstantiation
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
//省略部分代碼
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
//正式進入生命周期
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
//尋找InstantiationAwareBeanPostProcessor,并執行相應方法
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
//在回傳不為null的情況下,尋找BeanPostProcessor,執行相應方法
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
當resolveBeforeInstantiation回傳不為null的bean后,createBean會直接回傳,也就是說,后續的實體化、屬性賦值與初始化階段都不會進行,這一步,將會給BeanPostProcessor一個回傳代理而不是目前bean的機會,
resolveBeforeInstantiation核心的方法如下:
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
//獲取所有BeanPostProcessor的實作類
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//如果屬于InstantiationAwareBeanPostProcessor型別,則執行postProcessBeforeInstantiation方法
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//獲取所有BeanPostProcessor的實作類
for (BeanPostProcessor processor : getBeanPostProcessors()) {
//挨個執行postProcessAfterInitialization方法
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
2、BeanPostProcessor
BeanPostProcessor是容器提供給我們的一個擴展介面,也稱Bean的后置處理器,我們可以實作該介面,用來添加業務中特有的邏輯,
BeanPostProcessor實作類也是一個普通的Bean,那么Spring是怎么保證BeanPostProcessor實作類在開發人員寫的Bean之前加載的呢?
這就要回到我們最熟悉的refresh方法中
public void refresh() {
// 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);
// 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);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
其中registerBeanPostProcessors方法就會對BeanPostProcessor進行注冊,在finishBeanFactoryInitialization中再完成非懶加載的單例Bean的加載,
從而BeanPostProcessor就會在業務Bean之前加載,因此可以在業務Bean實體化前進行呼叫,
3、instantiateBean
現在可以進入doCreateBean中,createBeanInstance包含了實體化bean并封裝為BeanWrapper的邏輯,且內部提供了多種實體化的方式,
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
//將bean轉化為class物件
Class<?> beanClass = resolveBeanClass(mbd, beanName);
//基于Supplier實體化
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
//基于工廠方法實體化
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
//省略部分代碼
//基于有參建構式實體化
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
//基于無參建構式實體化
return instantiateBean(beanName, mbd);
}
有興趣的同學,可以深入到這幾種方式的內部,這里就不做探討了,
4、populateBean
在實體化結束后,將進入屬性賦值階段,
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//如果屬于InstantiationAwareBeanPostProcessor型別,則呼叫postProcessAfterInstantiation
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
//一旦任意一個InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation回傳false,屬性注入階段將不再進行,直接進入下一個階段
if (!continueWithPropertyPopulation) {
return;
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
//按照名稱注入
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
//按照型別注入
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
//省略掉InstantiationAwareBeanPostProcessor其他兩個擴展點及下面的依賴檢查
if (pvs != null) {
//屬性注入
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
到這里,實體化與屬性賦值階段結束,我們整理一下其中的擴展點

三、初始化階段
從doCreateBean內的initializeBean開始
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
//1.設定Aware相關依賴
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
//2.呼叫BeanPostProcessor的前置處理
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
//3.1呼叫InitializingBean的afterPropertiesSet方法
//3.2呼叫自定義的init method方法
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
//4.呼叫BeanPostProcessor的后置處理
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
1、設定Aware相關依賴
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
//如果bean實作了BeanNameAware介面,則設定BeanName
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
//如果bean實作了BeanClassLoaderAware介面,則設定BeanClassLoader
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
//如果bean實作了BeanFactoryAware介面,則設定BeanFactory
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
從這里可以看出,只要Bean實作了指定的Aware介面,Spring就會向Bean注入這些Aware相關資訊,
2、呼叫BeanPostProcessor的前置處理
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//獲取所有BeanPostProcessor的實作類
for (BeanPostProcessor processor : getBeanPostProcessors()) {
//挨個呼叫postProcessBeforeInitialization方法
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
這一步會獲取容器中所有BeanPostProcessor的實作類,挨個呼叫postProcessBeforeInitialization方法,在其回傳不為null的情況下,后一個結果會覆寫上一個結果,
當然在處理到ApplicationContextAwareProcessor的時候,會設定以下Aware依賴,
- EnvironmentAware
- EmbeddedValueResolverAware
- ResourceLoaderAware
- ApplicationEventPublisherAware
- MessageSourceAware
- ApplicationContextAware
在處理到InitDestroyAnnotationBeanPostProcessor,會找出被@PostConstruct注解修飾的方法,并執行,
3、invokeInitMethods
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
//如果實作了InitializingBean介面,則呼叫afterPropertiesSet方法
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();
}
}
//呼叫xml中宣告的init-method指定的方法
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);
}
}
}
4、呼叫BeanPostProcessor的后置處理
和前置處理類似,只是調用postProcessAfterInitialization方法,不再贅述,
因此,初始化程序又可以被細分為

四、銷毀階段
在容器關閉的時候,會進入Bean的銷毀階段,代碼從AbstractApplicationContext的close()方法開始
不急著進入close()方法,先看一下第一節代碼中最末尾的方法:
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
//如果Bean不是多例且需要在容器關閉時銷毀
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
if (mbd.isSingleton()) {
//給當前Bean系結一個DisposableBeanAdapter
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
// A bean with a custom 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, getBeanPostProcessors(), acc));
}
}
}
public void registerDisposableBean(String beanName, DisposableBean bean) {
synchronized (this.disposableBeans) {
this.disposableBeans.put(beanName, bean);
}
}
在registerDisposableBeanIfNecessary中,會對每一個需要在容器關閉時進行銷毀的單例Bean,系結對應的DisposableBeanAdapter物件,最后把這些Bean及其DisposableBeanAdapter放入進名稱為disposableBeans的map中,以供后續使用,
現在我們進入AbstractApplicationContext的close()方法
一路上兜兜轉轉,會進入到DefaultSingletonBeanRegistry的destroySingletons方法中
public void destroySingletons() {
String[] disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
destroySingleton(disposableBeanNames[i]);
}
//省略部分代碼
}
先拿到所有待銷毀Bean的名稱,挨個呼叫destroySingleton方法,一直往下走,最侄訓進入到DefaultSingletonBeanRegistry的destroyBean中
其中核心的一句
// Actually destroy the bean now...
bean.destroy();
按照beanName從disposableBeans中獲取到bean對應的DisposableBeanAdapter,呼叫其destroy方法
public void destroy() {
//呼叫被@PreDestroy注解修飾的方法
//具體可以跟進InitDestroyAnnotationBeanPostProcessor類
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
//如果實作了DisposableBean介面,則呼叫destroy方法
if (this.invokeDisposableBean) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((DisposableBean) this.bean).destroy();
return null;
}, this.acc);
} else {
((DisposableBean) this.bean).destroy();
}
}
//呼叫xml中自定義的destroy-method方法
if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
} else if (this.destroyMethodName != null) {
Method methodToCall = determineDestroyMethod(this.destroyMethodName);
if (methodToCall != null) {
invokeCustomDestroyMethod(methodToCall);
}
}
}
到這里,Bean的銷毀程序基本就結束了,我們使用一張圖來概括下:

五、生命周期的全流程
我們整個階段串聯起來

六、代碼驗證
待觀察的Bean
public class A implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
System.out.println("屬性賦值");
}
private A() {
System.out.println("實體化");
}
@PostConstruct
public void postConstruct() {
System.out.println("@PostConstruct指定的方法");
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("BeanClassLoaderAware.setBeanClassLoader");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("BeanFactoryAware.setBeanFactory");
}
@Override
public void setBeanName(String name) {
System.out.println("BeanNameAware.setBeanName");
}
@Override
public void afterPropertiesSet() {
System.out.println("InitializingBean.afterPropertiesSet");
}
public void initMethod() {
System.out.println("xml中init-method指定的方法");
}
@PreDestroy
public void preDestroy() {
System.out.println("@PreDestroy指定的方法");
}
@Override
public void destroy() {
System.out.println("DisposableBean.destroy");
}
public void destroyMethod() {
System.out.println("xml中destroy-method指定的方法");
}
}
自定義的BeanPostProcessor
public class BeanPostProcessorImpl implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("a")) {
System.out.println("BeanPostProcessor.postProcessBeforeInitialization");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("a")) {
System.out.println("BeanPostProcessor.postProcessAfterInitialization");
}
return bean;
}
}
自定義的InstantiationAwareBeanPostProcessorImpl
public class InstantiationAwareBeanPostProcessorImpl implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (beanName.equals("a")) {
System.out.println("InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation");
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if (beanName.equals("a")) {
System.out.println("InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation");
}
//如果這里回傳false,那么所有Bean將不進行屬性賦值
return true;
}
}
spring.xml配置
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.yang.ym"/>
<bean id="a" class="com.yang.ym.testBean.A" init-method="initMethod" destroy-method="destroyMethod">
<property name="id" value="1"/>
</bean>
<bean class="com.yang.ym.testBean.BeanPostProcessorImpl"/>
<bean class="com.yang.ym.testBean.InstantiationAwareBeanPostProcessorImpl"/>
</beans>
測驗類
@Test
public void get() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
A a = (A) context.getBean("a");
System.out.println("關閉容器");
context.close();
}
輸出結果:
InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
實體化
InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
屬性賦值
BeanNameAware.setBeanName
BeanClassLoaderAware.setBeanClassLoader
BeanFactoryAware.setBeanFactory
BeanPostProcessor.postProcessBeforeInitialization
@PostConstruct指定的方法
InitializingBean.afterPropertiesSet
xml中init-method指定的方法
BeanPostProcessor.postProcessAfterInitialization
關閉容器
@PreDestroy指定的方法
DisposableBean.destroy
xml中destroy-method指定的方法
七、總結
先記住4個大階段,實體化、屬性賦值、初始化與銷毀,
在生命周期內部,可以自定義Bean后置處理器以及實作介面的形式來進行擴展
- 容器級的擴展點,InstantiationAwareBeanPostProcessor與BeanPostProcessor,
- Bean級的擴展點,Aware相關介面,InitializingBean與DisposableBean,
此外,可以使用注解或xml配置形式,指定擴展點
- @PostConstruct注解
- @PreDestroy注解
- xml中init-method
- xml中destroy-method
那么再記憶生命周期的先后順序,就會容易很多:
getBean
- InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
- 實體化
- InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
- 屬性賦值
- Aware介面回呼
- BeanPostProcessor.postProcessBeforeInitialization
- @PostConstruct指定的方法
- InitializingBean.afterPropertiesSet
- xml中init-method指定的方法
- BeanPostProcessor.postProcessAfterInitialization
關閉容器后
- @PreDestroy指定的方法
- DisposableBean.destroy
- xml中destroy-method指定的方法
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/321220.html
標籤:java
上一篇:萌新成長計劃(開篇章)
