BeanPostProcessor註冊與Bean生命週期過程

疑問

後置處理器有什麼作用?

BeanPostProcessor是什麼時候被加載到Spring容器中的?

BeanPostProcessor保存在什麼地方?

什麼時候調用BeanPostProcessor的postProcessBeforeInitialization方法?

什麼時候調用BeanPostProcessor的postProcessAfterInitialization方法?

本文將帶著上述5個問題對Spring的後置處理器進行揭秘

SpringBoot啟動流程簡述

SpringBoot在啟動過程中,首先會對創建Spring應用上下文ApplicationContext,併為其準備環境變量Environment,然後會掃描包下面的所有bean,並對bean進行解析驗證,驗證通過後會將bean加載到Spring容器中,加載完成後會對所有的bean進行初始化(即完成bean的生命週期),在進行其生命週期的過程中就會調用BeanPostProcessor相關的方法,對bean進行包裝,如設置bean的屬性值等;在初始化bean之前,就會將對應的後置處理器加載到Spring容器中。

SpringBoot註冊BeanPostProcessor

在Spring組件開發過程中經常會使用到BeanPostProcessor接口,一個類實現了BeanPostProcessor接口,這個類就是一個後置處理器,而後置處理器的作用就是可以對bean進行代理及包裝。下面將介紹BeanPostProcessor的註冊過程

在AbstractApplicationContext類的下述方法中會對BeanPostProcessor進行註冊

registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory)

然後Spring會委託註冊後置處理器的代理類PostProcessorRegistrationDelegate來註冊BeanPostProcessor

public static void registerBeanPostProcessors(

ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

//從Spring容器beanFactory中找到所有實現了BeanPostProcessor接口的類名稱

String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

//省略其餘代碼...

//通過類名稱來創建具體的後置處理器 此處為偽代碼 Spring中會將BeanPostProcessor分為多種類型的BeanPostProcessor接口

List<beanpostprocessor> postProcessors = new ArrayList<>();/<beanpostprocessor>

for (String ppName : postProcessorNames) {

BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);

postProcessors.add(pp);

}

//獲取到的後置處理器實例後,將其註冊到beanFactory中

registerBeanPostProcessors(beanFactory, postProcessors);

//省略其餘代碼...

}

接著會遍歷List數組

private static void registerBeanPostProcessors(

ConfigurableListableBeanFactory beanFactory, List<beanpostprocessor> postProcessors) {/<beanpostprocessor>

for (BeanPostProcessor postProcessor : postProcessors) {

beanFactory.addBeanPostProcessor(postProcessor)

}

}

將後置處理器保存到AbstractBeanFactory類的下述屬性中,在後續的初始化bean生命週期過程中會遍歷所有後置處理,調用其postProcessBeforeInitialization和postProcessAfterInitialization方法

/** BeanPostProcessors to apply in createBean */

private final List<beanpostprocessor> beanPostProcessors = new ArrayList<>();/<beanpostprocessor>

@Override

public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {

Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");

this.beanPostProcessors.remove(beanPostProcessor);

//保存後置處理器

this.beanPostProcessors.add(beanPostProcessor);

}

Bean生命週期過程

後置處理器的調用就在bean的生命週期中完成,可參考BeanFactory接口類上的註釋,瞭解bean的整個生命週期過程

BeanPostProcessor註冊與Bean生命週期過程


在spring啟動過程中,會有很多次調用getBean方法來創建或獲取bean實例

@Override

public Object getBean(String name) throws BeansException {

return doGetBean(name, null, null, false);

}

@Override

public T getBean(String name, @Nullable Class requiredType) throws BeansException {

return doGetBean(name, requiredType, null, false);

}

@Override

public Object getBean(String name, Object... args) throws BeansException {

return doGetBean(name, null, args, false);

}

如果spring容器沒有創建好名稱為name的bean,就會先去調用下述方法去創建這個bean

AbstractAutowireCapableBeanFactory.createBean()

創建bean的過程中會先通過下述方法進行屬性填充

populateBean(beanName, mbd, instanceWrapper)

填充完成以後,接著去調用下述方法初始化bean

AbstractAutowireCapableBeanFactory.initializeBean(beanName, exposedObject, mbd)

初始化bean的過程就是bean的生命週期執行過程,而後置處理器BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法調用就在此過程中完成

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {

//省略部分代碼...

//調用Aware接口的setXXX方法

invokeAwareMethods(beanName, bean);

Object wrappedBean = bean;

if (mbd == null || !mbd.isSynthetic()) {

//調用BeanPostProcessor接口的BeanPostProcessorsBeforeInitialization方法

wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);

}

try {

//調用自定義的init-method方法

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()) {

//調用BeanPostProcessor接口的postProcessAfterInitialization方法

wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

}

return wrappedBean;

}

執行invokeAwareMethods時,會判斷當前bean是否實現XXXAware接口,如果實現了XXXAware接口,則會去調用setXXX方法

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

}

}

}

執行applyBeanPostProcessorsBeforeInitialization方法,會遍歷Spring容器中所有的後置處理器,而且會調用每個後置處理器的postProcessBeforeInitialization方法

@Override

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {

Object result = existingBean;

for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {

Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);

if (current == null) {

return result;

}

result = current;

}

return result;

}

執行invokeInitMethods方法,會先判斷當前的bean有沒有實現InitializingBean接口,如果實現了,則會調用InitializingBean接口的afterPropertiesSet()方法,然後判斷是否自定義了init-method,如果有,則會執行其init-method

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {

//省略部分代碼

//調用afterPropertiesSet方法

((InitializingBean) bean).afterPropertiesSet();

//判斷如果自定義了init-method,就會執行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);

}

}

}

最後執行applyBeanPostProcessorsAfterInitialization方法,會遍歷Spring容器中所有的後置處理器,而且會調用每個後置處理器的postProcessAfterInitialization方法

@Override

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)

throws BeansException {

Object result = existingBean;

for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {

Object current = beanProcessor.postProcessAfterInitialization(result, beanName);

if (current == null) {

return result;

}

result = current;

}

return result;

}

通過bean的生命週期執行過程,就可瞭解BeanPostProcessor的整個調用過程



分享到:


相關文章: