疑問
後置處理器有什麼作用?
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的整個生命週期過程
在spring啟動過程中,會有很多次調用getBean方法來創建或獲取bean實例
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
@Override
public
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的整個調用過程
閱讀更多 千本櫻散落 的文章