摘要:即,的后置處理器,它的作用就是在的初始化方法前跟后進行攔截處理。如何注冊后置處理器我們暫不作分析,著重說一下,后置處理器是如何工作的。
BeanPostProcessor即,Bean的后置處理器,它的作用就是在Bean的初始化方法前跟后進行攔截處理。我們都知道,要想在Bean的初始化方法前后進行工作,那必須在Bean實例創(chuàng)建完成之后,init方法執(zhí)行之前,后置處理器就已經(jīng)在容器中了,所以我們來到向容器中添加后置處理器的類AbstractApplicationContext,其中refresh()中的registerBeanPostProcessors(beanFactory)就是首先向容器中注冊我們所需要的所有后置處理器。如何注冊后置處理器我們暫不作分析,著重說一下,后置處理器是如何工作的。代碼實現(xiàn)
實現(xiàn)類:
@Component public class BeanPostProcessorImpl implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // 返回一個傳過來的對象 // 在初始化方法調(diào)用之前進行后置處理工作 // 什么時候調(diào)用呢?在init-method方法之前就調(diào)用了 System.out.println("postProcessBeforeInitialization======" + beanName + "======" + bean); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("postProcessAfterInitialization======" + beanName + "======" + bean); return bean; } }
配置類:
@Configuration @ComponentScan("com.nmys.story.springCore.springioc.beanpostprocessor_") public class Config01 { @Bean(initMethod = "init",destroyMethod = "destroy") public Train train(){ return new Train(); } }
實體類:
/** * @author 70KG * @Title: Train * @Description: * @date 2018/7/23下午11:31 * @From www.nmyswls.com */ public class Train { private String name = "火車"; private Integer length = 150; public Train() { System.out.println("Train構(gòu)造方法執(zhí)行。。。。。。"); } public void init() { System.out.println("Train的init方法執(zhí)行。。。。。。"); } public void destroy() { System.out.println("Train的destroy方法執(zhí)行。。。。。。"); } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getLength() { return length; } public void setLength(Integer length) { this.length = length; } }
測試類:
public class Test01 { @Test public void test() { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Config01.class); ac.close(); } }
打印結(jié)果:
Train構(gòu)造方法執(zhí)行。。。。。。 postProcessBeforeInitialization======train======com.nmys.story.springCore.springioc.beanpostprocessor_.Train@5aa9e4eb Train的init方法執(zhí)行。。。。。。 postProcessAfterInitialization======train======com.nmys.story.springCore.springioc.beanpostprocessor_.Train@5aa9e4eb Train的destroy方法執(zhí)行。。。。。。
結(jié)果分析:
首先Train構(gòu)造方法執(zhí)行創(chuàng)建對象,然后執(zhí)行了后置處理器的Before方法,然后才調(diào)用init方法,init方法執(zhí)行完成,再執(zhí)行后置處理器的After方法,最后容器關(guān)閉執(zhí)行銷毀方法。BeanPostProcessor原理分析
AnnotationConfigApplicationContext構(gòu)造方法中的refresh(); -> AbstractApplicationContext550行finishBeanFactoryInitialization(beanFactory);完成剩余Bean的初始化工作 -> AbstractApplicationContext869行beanFactory.preInstantiateSingletons(); -> DefaultListableBeanFactory760行g(shù)etBean(beanName); -> AbstractBeanFactory317行createBean(beanName, mbd, args); -> AbstractAutowireCapableBeanFactory503行doCreateBean(beanName, mbdToUse, args); -> AbstractAutowireCapableBeanFactory580行populateBean(beanName, mbd, instanceWrapper);在執(zhí)行初始化之前,首先給實例賦值 -> AbstractAutowireCapableBeanFactory581行exposedObject = initializeBean(beanName, exposedObject, mbd);準(zhǔn)備執(zhí)行初始化方法 -> AbstractAutowireCapableBeanFactory1700行wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); -> AbstractAutowireCapableBeanFactory1704行invokeInitMethods(beanName, wrappedBean, mbd); -> AbstractAutowireCapableBeanFactory1712行wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
分析AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsBeforeInitialization方法:
@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; }
首先獲取到所有的后置處理器getBeanPostProcessors()
在for循環(huán)中依次調(diào)用后置處理器的方法beanProcessor.postProcessBeforeInitialization(result, beanName);
進入postProcessBeforeInitialization方法(這個方法必須在debug過程中才可以進入)
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException { AccessControlContext acc = null; if (System.getSecurityManager() != null && (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware || bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) { acc = this.applicationContext.getBeanFactory().getAccessControlContext(); } if (acc != null) { AccessController.doPrivileged((PrivilegedAction
private void invokeAwareInterfaces(Object bean) { if (bean instanceof Aware) { if (bean instanceof EnvironmentAware) { ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment()); } if (bean instanceof EmbeddedValueResolverAware) { ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver); } if (bean instanceof ResourceLoaderAware) { ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext); } if (bean instanceof ApplicationEventPublisherAware) { ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext); } if (bean instanceof MessageSourceAware) { ((MessageSourceAware) bean).setMessageSource(this.applicationContext); } if (bean instanceof ApplicationContextAware) { ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); } } }
來到ApplicationContextAwareProcessor類的79行,首先判斷此bean是不是各種的Aware,如果是它列舉的那幾個Aware就獲取Bean工廠的權(quán)限,可以向容器中導(dǎo)入相關(guān)的上下文環(huán)境,目的是為了Bean實例能夠獲取到相關(guān)的上下文,如果不是(顯然它也不是)它列舉的幾個Aware,那就調(diào)用invokeAwareInterfaces(bean),向容器中添加相關(guān)接口的上下文環(huán)境,顯然我們自己的實現(xiàn)類也不屬于Aware接口,所以這個處理結(jié)果直接將Bean返回,不做任何處理。ok,這樣初始化之前的方法就分析完了,初始化之后的方法跟前面的流程一模一樣。
總結(jié)BeanPostProcessor就是在Bean實例創(chuàng)建之后,在進行populateBean賦值之后,init初始化方法之前進行一次調(diào)用,init方法之后進行一次調(diào)用,這樣一來,整個Bean的生命周期,全部掌控在了Spring之下,包括Bean實例創(chuàng)建new Instance(),賦值前后populateBean(),初始化前后init(),銷毀前后destroy()。從此Bean便身不由己了。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/73224.html
摘要:也是屬于方法調(diào)用棧的一環(huán),進去有類似一段偽代碼這段代碼通過遍歷得到所有的,然后挨個執(zhí)行重寫的方法,倘若有一個方法返回的為,那么循環(huán)就會跳出,意味著下面的方法不會被執(zhí)行。 Spring源碼原理篇--容器初始化&Bean后置處理器 本篇主要是講解IOC容器初始化過程中大體進行了哪一些工作,以及Bean后置處理器的工作原理和BeanPostProcessor在底層的使用。 環(huán)境準(zhǔn)備 編譯器...
摘要:本文是容器源碼分析系列文章的第一篇文章,將會著重介紹的一些使用方法和特性,為后續(xù)的源碼分析文章做鋪墊。我們可以通過這兩個別名獲取到這個實例,比如下面的測試代碼測試結(jié)果如下本小節(jié),我們來了解一下這個特性。 1. 簡介 Spring 是一個輕量級的企業(yè)級應(yīng)用開發(fā)框架,于 2004 年由 Rod Johnson 發(fā)布了 1.0 版本。經(jīng)過十幾年的迭代,現(xiàn)在的 Spring 框架已經(jīng)非常成熟了...
摘要:在上文中,我實現(xiàn)了一個很簡單的和容器。比如,我們所熟悉的就是在這里將切面邏輯織入相關(guān)中的。初始化的工作算是結(jié)束了,此時處于就緒狀態(tài),等待外部程序的調(diào)用。其中動態(tài)代理只能代理實現(xiàn)了接口的對象,而動態(tài)代理則無此限制。 1. 背景 本文承接上文,來繼續(xù)說說 IOC 和 AOP 的仿寫。在上文中,我實現(xiàn)了一個很簡單的 IOC 和 AOP 容器。上文實現(xiàn)的 IOC 和 AOP 功能很單一,且 I...
摘要:如果依賴靠構(gòu)造器方式注入,則無法處理,直接會報循環(huán)依賴異常。光繼承這個接口還不夠,繼承這個接口只能獲取,要想讓生效,還需要拿到切面對象包含和才行。有了目標(biāo)對象,所有的切面類,此時就可以為生成代理對象了。 Spring 是一個輕量級的 J2EE 開源框架,其目標(biāo)是降低企業(yè)級應(yīng)用開發(fā)難度,提高企業(yè)級應(yīng)用開發(fā)效率。在日程開發(fā)中,我們會經(jīng)常使用 Spring 框架去構(gòu)建應(yīng)用。所以作為一個經(jīng)常使...
摘要:關(guān)于創(chuàng)建實例的過程,我將會分幾篇文章進行分析。源碼分析創(chuàng)建實例的入口在正式分析方法前,我們先來看看方法是在哪里被調(diào)用的。時,表明方法不存在,此時拋出異常。該變量用于表示是否提前暴露單例,用于解決循環(huán)依賴。 1. 簡介 在上一篇文章中,我比較詳細的分析了獲取 bean 的方法,也就是getBean(String)的實現(xiàn)邏輯。對于已實例化好的單例 bean,getBean(String) ...
閱讀 1808·2021-09-03 10:50
閱讀 1338·2019-08-30 15:55
閱讀 3379·2019-08-30 15:52
閱讀 1241·2019-08-30 15:44
閱讀 952·2019-08-30 15:44
閱讀 3325·2019-08-30 14:23
閱讀 3558·2019-08-28 17:51
閱讀 2297·2019-08-26 13:52