有些小夥伴問我,學習Spring是否是不用學習到這麼細節的程度啊?感受這些細節的部分在實際工做中使用不到啊,我到底需不須要學習到這麼細節的程度呢?個人答案是:有必要學習到這麼細節的程度,並且是有機會、有條件必定要學!吃透Spring的原理和源碼!每每拉開人與人之間差距的就是這些細節的部分,當前只要是使用Java技術棧開發的Web項目,幾乎都會使用Spring框架。並且目前各招聘網站上對於Java開發的要求幾乎清一色的都是熟悉或者精通Spring。因此,你,頗有必要學習Spring的細節知識點。html
項目工程源碼已經提交到GitHub:https://github.com/sunshinelyz/spring-annotationjava
首先,咱們來看下BeanPostProcessor的源碼,看下它究竟是個什麼鬼,以下所示。git
package org.springframework.beans.factory.config; import org.springframework.beans.BeansException; import org.springframework.lang.Nullable; public interface BeanPostProcessor { @Nullable default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } @Nullable default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } }
從源碼能夠看出:BeanPostProcessor是一個接口,其中有兩個方法,postProcessBeforeInitialization和postProcessAfterInitialization兩個方法,這兩個方法分別是在spring容器中的bean初始化先後執行,因此spring容器中的每個bean對象初始化先後,都會執行BeanPostProcessor接口的實現類的這兩個方法。github
也就是說,postProcessBeforeInitialization方法會在bean實例化和屬性設置以後,自定義初始化方法以前被調用,而postProcessAfterInitialization方法會在自定義初始化方法以後被調用。當容器中存在多個BeanPostProcessor的實現類時,會按照它們在容器中註冊的順序執行。對於自定義BeanPostProcessor實現類,還可讓其實現Ordered接口自定義排序。spring
所以咱們能夠在每一個bean對象初始化先後,加上本身的邏輯。實現方式:自定義一個BeanPostProcessor接口的實現類MyBeanPostProcessor,而後在類MyBeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法裏面寫上本身的邏輯。bash
咱們建立一個MyBeanPostProcessor類,實現BeanPostProcessor接口,以下所示。微信
package io.mykit.spring.plugins.register.bean; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component; /** * @author binghe * @version 1.0.0 * @description 測試BeanPostProcessor */ @Component public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("調用了postProcessBeforeInitialization方法,beanName = " + beanName + ", bean = " + bean); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("調用了postProcessAfterInitialization,beanName = " + beanName + ", bean = " + bean); return bean; } }
接下來,咱們運行BeanLifeCircleTest類的testBeanLifeCircle04()方法,輸出的結果信息以下所示。框架
調用了postProcessBeforeInitialization方法,beanName = animalConfig, bean = io.mykit.spring.plugins.register.config.AnimalConfig$$EnhancerBySpringCGLIB$$e8ab4f2e@56528192 調用了postProcessAfterInitialization,beanName = animalConfig, bean = io.mykit.spring.plugins.register.config.AnimalConfig$$EnhancerBySpringCGLIB$$e8ab4f2e@56528192 Cat類的構造方法... 調用了postProcessBeforeInitialization方法,beanName = cat, bean = io.mykit.spring.plugins.register.bean.Cat@1b1473ab Cat的postConstruct()方法... Cat的init()方法... 調用了postProcessAfterInitialization,beanName = cat, bean = io.mykit.spring.plugins.register.bean.Cat@1b1473ab Cat的preDestroy()方法... Cat的destroy()方法...
能夠看到,postProcessBeforeInitialization方法會在bean實例化和屬性設置以後,自定義初始化方法以前被調用,而postProcessAfterInitialization方法會在自定義初始化方法以後被調用。ide
也可讓實現Ordered接口自定義排序,以下所示。post
package io.mykit.spring.plugins.register.bean; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.core.Ordered; import org.springframework.stereotype.Component; /** * @author binghe * @version 1.0.0 * @description 測試BeanPostProcessor */ @Component public class MyBeanPostProcessor implements BeanPostProcessor, Ordered { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("調用了postProcessBeforeInitialization方法,beanName = " + beanName + ", bean = " + bean); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("調用了postProcessAfterInitialization,beanName = " + beanName + ", bean = " + bean); return bean; } @Override public int getOrder() { return 3; } }
再次運行BeanLifeCircleTest類的testBeanLifeCircle04()方法,輸出的結果信息以下所示。
調用了postProcessBeforeInitialization方法,beanName = animalConfig, bean = io.mykit.spring.plugins.register.config.AnimalConfig$$EnhancerBySpringCGLIB$$b045438a@1ed1993a 調用了postProcessAfterInitialization,beanName = animalConfig, bean = io.mykit.spring.plugins.register.config.AnimalConfig$$EnhancerBySpringCGLIB$$b045438a@1ed1993a Cat類的構造方法... 調用了postProcessBeforeInitialization方法,beanName = cat, bean = io.mykit.spring.plugins.register.bean.Cat@36c88a32 Cat的postConstruct()方法... Cat的init()方法... 調用了postProcessAfterInitialization,beanName = cat, bean = io.mykit.spring.plugins.register.bean.Cat@36c88a32 Cat的preDestroy()方法... Cat的destroy()方法...
後置處理器用於bean對象初始化先後進行邏輯加強。spring提供了BeanPostProcessor的不少實現類,例如AutowiredAnnotationBeanPostProcessor用於@Autowired註解的實現,AnnotationAwareAspectJAutoProxyCreator用於SpringAOP的動態代理等等。
除此以外,咱們還能夠自定義BeanPostProcessor的實現類,在其中寫入須要的邏輯。下面以AnnotationAwareAspectJAutoProxyCreator爲例,說明後置處理器是怎樣工做的。咱們都知道springAOP的實現原理是動態代理,最終放入容器的是代理類的對象,而不是bean自己的對象,那麼spring是何時作到這一步的?就是在AnnotationAwareAspectJAutoProxyCreator後置處理器的postProcessAfterInitialization方法,即bean對象初始化完成以後,後置處理器會判斷該bean是否註冊了切面,若是是,則生成代理對象注入容器。Spring中的關鍵代碼以下所示。
/** * Create a proxy with the configured interceptors if the bean is * identified as one to proxy by the subclass. * @see #getAdvicesAndAdvisorsForBean */ @Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (this.earlyProxyReferences.remove(cacheKey) != bean) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
好了,我們今天就聊到這兒吧!別忘了給個在看和轉發,讓更多的人看到,一塊兒學習一塊兒進步!!
項目工程源碼已經提交到GitHub:https://github.com/sunshinelyz/spring-annotation
若是以爲文章對你有點幫助,請微信搜索並關注「 冰河技術 」微信公衆號,跟冰河學習Spring註解驅動開發。公衆號回覆「spring註解」關鍵字,領取Spring註解驅動開發核心知識圖,讓Spring註解驅動開發再也不迷茫。
部分參考:https://www.cnblogs.com/dubhlinn/p/10668156.html