成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Spring源碼分析:BeanPostProcessor原理

jackwang / 1587人閱讀

摘要:即,的后置處理器,它的作用就是在的初始化方法前跟后進行攔截處理。如何注冊后置處理器我們暫不作分析,著重說一下,后置處理器是如何工作的。

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) () -> {
            invokeAwareInterfaces(bean);
            return null;
        }, acc);
    }
    else {
        invokeAwareInterfaces(bean);
    }
    return bean;
}

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

相關(guān)文章

  • Spring源碼原理篇(一)

    摘要:也是屬于方法調(diào)用棧的一環(huán),進去有類似一段偽代碼這段代碼通過遍歷得到所有的,然后挨個執(zhí)行重寫的方法,倘若有一個方法返回的為,那么循環(huán)就會跳出,意味著下面的方法不會被執(zhí)行。 Spring源碼原理篇--容器初始化&Bean后置處理器 本篇主要是講解IOC容器初始化過程中大體進行了哪一些工作,以及Bean后置處理器的工作原理和BeanPostProcessor在底層的使用。 環(huán)境準(zhǔn)備 編譯器...

    Acceml 評論0 收藏0
  • Spring IOC 容器源碼分析系列文章導(dǎo)讀

    摘要:本文是容器源碼分析系列文章的第一篇文章,將會著重介紹的一些使用方法和特性,為后續(xù)的源碼分析文章做鋪墊。我們可以通過這兩個別名獲取到這個實例,比如下面的測試代碼測試結(jié)果如下本小節(jié),我們來了解一下這個特性。 1. 簡介 Spring 是一個輕量級的企業(yè)級應(yīng)用開發(fā)框架,于 2004 年由 Rod Johnson 發(fā)布了 1.0 版本。經(jīng)過十幾年的迭代,現(xiàn)在的 Spring 框架已經(jīng)非常成熟了...

    NSFish 評論0 收藏0
  • 仿照 Spring 實現(xiàn)簡單的 IOC 和 AOP - 下篇

    摘要:在上文中,我實現(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...

    AlexTuan 評論0 收藏0
  • Spring bean的生命流程

    摘要:如果依賴靠構(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)常使...

    趙連江 評論0 收藏0
  • Spring IOC 容器源碼分析 - 創(chuàng)建單例 bean 的過程

    摘要:關(guān)于創(chuàng)建實例的過程,我將會分幾篇文章進行分析。源碼分析創(chuàng)建實例的入口在正式分析方法前,我們先來看看方法是在哪里被調(diào)用的。時,表明方法不存在,此時拋出異常。該變量用于表示是否提前暴露單例,用于解決循環(huán)依賴。 1. 簡介 在上一篇文章中,我比較詳細的分析了獲取 bean 的方法,也就是getBean(String)的實現(xiàn)邏輯。對于已實例化好的單例 bean,getBean(String) ...

    mochixuan 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<