淺談Spring中幾個(gè)PostProcessor的區(qū)別與聯(lián)系
按照?qǐng)?zhí)行的順序,可以分為以下幾個(gè)步驟:
BeanDefinitionRegistryPostProcessor 是在注冊(cè) Bean 定義信息前后調(diào)用;
BeanFactoryPostProcessor 是在創(chuàng)建 Bean 前后調(diào)用;
BeanPostProcessor 是在初始化 Bean 前后調(diào)用;
其中 BeanDefinitionRegistryPostProcessor 是 BeanFactoryPostProcessor 的子類,所以可以使用前者代替后者實(shí)現(xiàn)功能。
查看 IOC 容器創(chuàng)建時(shí)的調(diào)用流程refresh 方法的代碼如下:
// 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();
其中的 invokeBeanFactoryPostProcessors 就執(zhí)行了注冊(cè)定義信息和創(chuàng)建 Bean 的方法;而 finishBeanFactoryInitialization 執(zhí)行了初始化 Bean 的方法。
具體的執(zhí)行順序大家可以自行打斷點(diǎn)調(diào)試,由于涉及的源碼過(guò)多,這里不再展示。
spring-postProcessor的執(zhí)行時(shí)機(jī)spring bean 的生命周期粗糙的分為以下步驟。
實(shí)例化(創(chuàng)建一個(gè)屬性都為空的對(duì)象)---------》屬性填充(populateBean,下文中這個(gè)步驟我都稱為初始化)-----------》init方法的執(zhí)行(invokerInitMethods,下文稱為init)
postprocessor的方法就是穿插在這三個(gè)大的步驟中。
BeanPostProcessor:postProcessBeforeInitialization調(diào)用時(shí)機(jī)
向上找調(diào)用者:
繼續(xù)向上:
看以看出populateBean(初始化bean)-------------------》beanpostBeforeInitialization---------------------------------->invokeinitMethods(配置的init-method)
postProcessAfterInitialization調(diào)用時(shí)機(jī):向上:
可以看出在init-method方法之后
看以看出populateBean(初始化bean)-------------------》beanpostBeforeInitialization---------------------------------->invokeinitMethods(配置的init-method)------->postProcessAfterInitialization
public class MBeanPostProcessor implements BeanPostProcessor { @Override //populateBean之后 invokeinitMethods之前 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println('post bean before! :'+beanName);return bean; } @Override //invokeinitMethods之后 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println('post bean after!'+beanName);return bean; }}
另一個(gè)重要的是:
InstantiationAwareBeanPostProcessorpostProcessBeforeInstantiation調(diào)用時(shí)機(jī):
向上找調(diào)用者:
繼續(xù)向上:
可以看出是在實(shí)例化之前:(也就是反射創(chuàng)建對(duì)象之前,如果postProcessBeforeInstantiation創(chuàng)建了一個(gè)非空的對(duì)象,則不會(huì)走實(shí)例化步驟。)
postProcessAfterInstantiation調(diào)用時(shí)機(jī):
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { PropertyValues pvs = mbd.getPropertyValues(); if (bw == null) { if (!pvs.isEmpty()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, 'Cannot apply property values to null instance'); } else { // Skip property population phase for null instance. return; } } // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. boolean continueWithPropertyPopulation = true; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; //在這里執(zhí)行 if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } if (!continueWithPropertyPopulation) { return; } 省略。。。。。 applyPropertyValues(beanName, mbd, bw, pvs);}
可以看出是在在初始化之前,具體是屬性填充之前。(初始化之前,實(shí)例化之后) 如果返回fales,則不會(huì)繼續(xù)初始化,即不會(huì)屬性填充。
postProcessPropertyValues調(diào)用時(shí)機(jī):
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { PropertyValues pvs = mbd.getPropertyValues(); if (bw == null) { if (!pvs.isEmpty()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, 'Cannot apply property values to null instance'); } else { // Skip property population phase for null instance. return; } } // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. boolean continueWithPropertyPopulation = true; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } if (!continueWithPropertyPopulation) { return; } if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); if (hasInstAwareBpps || needsDepCheck) { PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); if (hasInstAwareBpps) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } } if (needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); } } applyPropertyValues(beanName, mbd, bw, pvs);}
在postProcessAfterInstantiation之后,applyPropertyValues之前。(屬性填充之前修改屬性值)
總結(jié): 執(zhí)行順序 1.postProcessBeforeInstantiation(實(shí)現(xiàn)這個(gè)方法可以做自定義實(shí)例化) 2.實(shí)例化 3.postProcessAfterInstantiation(是否要初始化) 4.postProcessPropertyValues(修改屬性) 5.初始化(屬性填充)(populateBean) 6.postProcesstBeforeInitialization( 自定義init方法執(zhí)行之前) 7.invokeinitMethods(執(zhí)行自定義的init方法) 8.postProcessAfterInitialization(自定義init方法執(zhí)行之后)如果加上aware
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
1. jsp實(shí)現(xiàn)簡(jiǎn)單用戶7天內(nèi)免登錄2. 三個(gè)不常見的 HTML5 實(shí)用新特性簡(jiǎn)介3. asp批量添加修改刪除操作示例代碼4. jsp+servlet實(shí)現(xiàn)猜數(shù)字游戲5. 刪除docker里建立容器的操作方法6. msxml3.dll 錯(cuò)誤 800c0019 系統(tǒng)錯(cuò)誤:-2146697191解決方法7. CSS3實(shí)現(xiàn)動(dòng)態(tài)翻牌效果 仿百度貼吧3D翻牌一次動(dòng)畫特效8. 概述IE和SQL2k開發(fā)一個(gè)XML聊天程序9. 推薦一個(gè)好看Table表格的css樣式代碼詳解10. asp在iis7報(bào)錯(cuò)行號(hào)不準(zhǔn)問(wèn)題的解決方法
