摘要:即,的后置處理器,它的作用就是在的初始化方法前跟后進行攔截處理。如何注冊后置處理器我們暫不作分析,著重說一下,后置處理器是如何工作的。
BeanPostProcessor即,Bean的后置處理器,它的作用就是在Bean的初始化方法前跟后進行攔截處理。我們都知道,要想在Bean的初始化方法前后進行工作,那必須在Bean實例創建完成之后,init方法執行之前,后置處理器就已經在容器中了,所以我們來到向容器中添加后置處理器的類AbstractApplicationContext,其中refresh()中的registerBeanPostProcessors(beanFactory)就是首先向容器中注冊我們所需要的所有后置處理器。如何注冊后置處理器我們暫不作分析,著重說一下,后置處理器是如何工作的。代碼實現
實現類:
@Component public class BeanPostProcessorImpl implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // 返回一個傳過來的對象 // 在初始化方法調用之前進行后置處理工作 // 什么時候調用呢?在init-method方法之前就調用了 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構造方法執行。。。。。。"); } public void init() { System.out.println("Train的init方法執行。。。。。。"); } public void destroy() { System.out.println("Train的destroy方法執行。。。。。。"); } 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(); } }
打印結果:
Train構造方法執行。。。。。。 postProcessBeforeInitialization======train======com.nmys.story.springCore.springioc.beanpostprocessor_.Train@5aa9e4eb Train的init方法執行。。。。。。 postProcessAfterInitialization======train======com.nmys.story.springCore.springioc.beanpostprocessor_.Train@5aa9e4eb Train的destroy方法執行。。。。。。
結果分析:
首先Train構造方法執行創建對象,然后執行了后置處理器的Before方法,然后才調用init方法,init方法執行完成,再執行后置處理器的After方法,最后容器關閉執行銷毀方法。BeanPostProcessor原理分析
AnnotationConfigApplicationContext構造方法中的refresh(); -> AbstractApplicationContext550行finishBeanFactoryInitialization(beanFactory);完成剩余Bean的初始化工作 -> AbstractApplicationContext869行beanFactory.preInstantiateSingletons(); -> DefaultListableBeanFactory760行getBean(beanName); -> AbstractBeanFactory317行createBean(beanName, mbd, args); -> AbstractAutowireCapableBeanFactory503行doCreateBean(beanName, mbdToUse, args); -> AbstractAutowireCapableBeanFactory580行populateBean(beanName, mbd, instanceWrapper);在執行初始化之前,首先給實例賦值 -> AbstractAutowireCapableBeanFactory581行exposedObject = initializeBean(beanName, exposedObject, mbd);準備執行初始化方法 -> 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循環中依次調用后置處理器的方法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工廠的權限,可以向容器中導入相關的上下文環境,目的是為了Bean實例能夠獲取到相關的上下文,如果不是(顯然它也不是)它列舉的幾個Aware,那就調用invokeAwareInterfaces(bean),向容器中添加相關接口的上下文環境,顯然我們自己的實現類也不屬于Aware接口,所以這個處理結果直接將Bean返回,不做任何處理。ok,這樣初始化之前的方法就分析完了,初始化之后的方法跟前面的流程一模一樣。
總結BeanPostProcessor就是在Bean實例創建之后,在進行populateBean賦值之后,init初始化方法之前進行一次調用,init方法之后進行一次調用,這樣一來,整個Bean的生命周期,全部掌控在了Spring之下,包括Bean實例創建new Instance(),賦值前后populateBean(),初始化前后init(),銷毀前后destroy()。從此Bean便身不由己了。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/73224.html
摘要:也是屬于方法調用棧的一環,進去有類似一段偽代碼這段代碼通過遍歷得到所有的,然后挨個執行重寫的方法,倘若有一個方法返回的為,那么循環就會跳出,意味著下面的方法不會被執行。 Spring源碼原理篇--容器初始化&Bean后置處理器 本篇主要是講解IOC容器初始化過程中大體進行了哪一些工作,以及Bean后置處理器的工作原理和BeanPostProcessor在底層的使用。 環境準備 編譯器...
摘要:本文是容器源碼分析系列文章的第一篇文章,將會著重介紹的一些使用方法和特性,為后續的源碼分析文章做鋪墊。我們可以通過這兩個別名獲取到這個實例,比如下面的測試代碼測試結果如下本小節,我們來了解一下這個特性。 1. 簡介 Spring 是一個輕量級的企業級應用開發框架,于 2004 年由 Rod Johnson 發布了 1.0 版本。經過十幾年的迭代,現在的 Spring 框架已經非常成熟了...
摘要:在上文中,我實現了一個很簡單的和容器。比如,我們所熟悉的就是在這里將切面邏輯織入相關中的。初始化的工作算是結束了,此時處于就緒狀態,等待外部程序的調用。其中動態代理只能代理實現了接口的對象,而動態代理則無此限制。 1. 背景 本文承接上文,來繼續說說 IOC 和 AOP 的仿寫。在上文中,我實現了一個很簡單的 IOC 和 AOP 容器。上文實現的 IOC 和 AOP 功能很單一,且 I...
摘要:如果依賴靠構造器方式注入,則無法處理,直接會報循環依賴異常。光繼承這個接口還不夠,繼承這個接口只能獲取,要想讓生效,還需要拿到切面對象包含和才行。有了目標對象,所有的切面類,此時就可以為生成代理對象了。 Spring 是一個輕量級的 J2EE 開源框架,其目標是降低企業級應用開發難度,提高企業級應用開發效率。在日程開發中,我們會經常使用 Spring 框架去構建應用。所以作為一個經常使...
摘要:關于創建實例的過程,我將會分幾篇文章進行分析。源碼分析創建實例的入口在正式分析方法前,我們先來看看方法是在哪里被調用的。時,表明方法不存在,此時拋出異常。該變量用于表示是否提前暴露單例,用于解決循環依賴。 1. 簡介 在上一篇文章中,我比較詳細的分析了獲取 bean 的方法,也就是getBean(String)的實現邏輯。對于已實例化好的單例 bean,getBean(String) ...
閱讀 1792·2021-09-03 10:50
閱讀 1327·2019-08-30 15:55
閱讀 3369·2019-08-30 15:52
閱讀 1231·2019-08-30 15:44
閱讀 935·2019-08-30 15:44
閱讀 3319·2019-08-30 14:23
閱讀 3551·2019-08-28 17:51
閱讀 2291·2019-08-26 13:52