javascript
Spring的9处调用后置处理器
在Sping的整個生命周期中,有9個地方調用后置處理器。這些后置處理器是spring實現自定義功能或者擴展spring的核心所在
一、實例化前
該方法屬于InstantiationAwareBeanPostProcessor后置處理器
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {@Nullabledefault Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {return null;}default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {return true;}@Nullabledefault PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)throws BeansException {return null;}@Deprecated@Nullabledefault PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {return pvs;}}該方法的意思其實也體現到名字上了,就是在實例化之前做些什么。
如果該方法返回非空,代表整個創建流程提前結束,也就是說后面什么屬性設置,bean的初始化等等都不會執行了,所以重寫該方法一定要謹慎。這個方法一般會和 applyBeanPostProcessorsAfterInitialization后置結處理器結合使用,這個處理可是實現aop的核心,這個后面在分析。
因為如果你在applyBeanPostProcessorsBeforeInstantiation中返回非空后,后面spring的流程就不會走了,但是如果你有個切面是想代理這個類,那就沒有辦法了,所以applyBeanPostProcessorsBeforeInstantiation返回非空后會調用applyBeanPostProcessorsAfterInitialization執行aop代理
至于網上說的說法:
如果這里出現了aop的切面類,就會有InstantiationAwareBeanPostProcessor的子處理器進行類的過濾,出現@AspectJ的類標記為不需要代理的類,會被放入map中我目前不理解,我自己寫了一個切面類,結果還是和正常類走相同的流程。
二、實例bean前決定構造器
在createBeanInstance中的方法determineConstructorsFromBeanPostProcessors中會調用SmartInstantiationAwareBeanPostProcessor 后置處理器的determineCandidateConstructors方法。
2.1 SmartInstantiationAwareBeanPostProcessor
該構造器主要就是為了預測最終bean的類型(predicting the eventual type of a processed bean)。
2.2 determineCandidateConstructors
該方法也是此處構造器的真正要做的事情。就是為了決定實例化bean的構造器
private DeptService service;public DeptController(@Autowired DeptService service){this.service = service; }比如這種情況,肯定不走默認的構造函數,spring就會在determineCandidateConstructors中決定出這個有參數的構造器,然后創建實例的時候回檢查參數是否有@Autowired的,在構造的時候就會把service給創建好
三、剛創建好實例之后
在createBeanInstance之后,這個時候bean的屬性、初始化方法等等都沒有創建好,基本屬于空白對象。然后在方法applyMergedBeanDefinitionPostProcessors中執行類MergedBeanDefinitionPostProcessor的后置處理
3.1 MergedBeanDefinitionPostProcessor
這個類主要用來更改或者豐富bean的定義的元數據信息。
3.2 方法postProcessMergedBeanDefinition
可見主要是為了后面的流程進行的一些輔助動作。
還是為了后面的流程進行的一些輔助動作。
四、解決循環依賴
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {Object exposedObject = bean;if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);}}}return exposedObject;}上面這段源碼是在創建好bean后,如果開啟了循環依賴,那么會執行
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));這個時候就來到了主角 getEarlyBeanReference這里。
可見該后置處理器屬于SmartInstantiationAwareBeanPostProcessor,這里到底是做什么呢?
4.1 AbstractAutoProxyCreator
改具體子類實現了SmartInstantiationAwareBeanPostProcessor接口。
public Object getEarlyBeanReference(Object bean, String beanName) {Object cacheKey = getCacheKey(bean.getClass(), beanName);this.earlyProxyReferences.put(cacheKey, bean);return wrapIfNecessary(bean, beanName, cacheKey);}這個代碼就是返回aop代碼的代碼。 所以該后置處理器有個功能就是返回aop的代理
五、實例化后
在屬性填充方法populateBean中
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;}}}}改后置處理器來自InstantiationAwareBeanPostProcessor,調用其中的postProcessAfterInstantiation
改方法功能也簡單,就是判斷是否進行屬性注入。
六 設置屬性前
for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;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;}}改后置處理器用在 在工廠將給定的屬性值應用到給定bean之前,對給定的屬性值進行后處理。你可以進行一些檢查,比如某個屬性是 “required”的,但是這個屬性需要的引用卻是空,這個時候可以進行一些檢查工作。還有dubbo的注解 @DubboReference這個注解,就是在此處 替換需要注入的類來實現的。
七 執行初始化方法前
if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}改代碼是在方法initializeBean中調用的。applyBeanPostProcessorsBeforeInitialization詳細調用是
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;for (BeanPostProcessor processor : getBeanPostProcessors()) {Object current = processor.postProcessBeforeInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;}可以看到他的引用是接口BeanPostProcessor這個接口屬于頂級接口,他的子類太多了,其中有個出名的是CommonAnnotationBeanPostProcessor 該類的結構圖是
其中他的父類InitDestroyAnnotationBeanPostProcessor是個重點角色,在改類中的postProcessBeforeInitialization方法中就執行了大名鼎鼎的 @PostConstruct 注解的方法。
八 執行初始化方法后
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;for (BeanPostProcessor processor : getBeanPostProcessors()) {Object current = processor.postProcessAfterInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;}鼎鼎大名的aop就是在這里進行實現的。具體的后置處理器是AbstractAutoProxyCreator
九 銷毀bean容器的時候調用
具體后置處理器InitDestroyAnnotationBeanPostProcessor
然后調用的方法是postProcessBeforeDestruction
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());try {metadata.invokeDestroyMethods(bean, beanName);}catch (InvocationTargetException ex) {String msg = "Destroy method on bean with name '" + beanName + "' threw an exception";if (logger.isDebugEnabled()) {logger.warn(msg, ex.getTargetException());}else {logger.warn(msg + ": " + ex.getTargetException());}}catch (Throwable ex) {logger.warn("Failed to invoke destroy method on bean with name '" + beanName + "'", ex);}}什么是destory方法呢,被javax.annotation.PreDestroy 注解的的方法。
總結
以上是生活随笔為你收集整理的Spring的9处调用后置处理器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ChatGpt常用指令大全
- 下一篇: 关于扁平化界面风格的设计美学讨论