最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

spring初始化源碼之關(guān)鍵類和擴(kuò)展接口詳解

 更新時(shí)間:2023年04月28日 11:01:33   作者:雷X峰  
Spring就是一個(gè)大工廠,可以將所有對(duì)象的創(chuàng)建和依賴關(guān)系的維護(hù)交給Spring管理,下面這篇文章主要給大家介紹了關(guān)于spring初始化源碼之關(guān)鍵類和擴(kuò)展接口的相關(guān)資料,需要的朋友可以參考下

前言

spring的IOC容器初始化流程很復(fù)雜,本文只關(guān)注流程中的關(guān)鍵點(diǎn),勾勒出主要輪廓,對(duì)容器的初始化有一個(gè)整體認(rèn)識(shí),以下基于spring的5.1.2.RELEASE分析,本文演示代碼地址:https://github.com/amapleleaf/spring-code.git

本文分為兩部分:《spring初始化源碼淺析之關(guān)鍵類和擴(kuò)展接口》、《spring初始化源碼淺析之代碼淺析

1、關(guān)鍵接口和類

1.1、關(guān)鍵類之 DefaultListableBeanFactory

該類核心功能:

1、提供注冊(cè)、獲取等等與BeanDefinition對(duì)象操作相關(guān)的方法,BeanDefinition緩存在DefaultListableBeanFactory的beanDefinitionMap變量(ConcurrentHashMap類型)

2、提供創(chuàng)建、注冊(cè)、獲取、單例等等跟bean對(duì)象操作相關(guān)的方法供ApplicationContext使用,bean對(duì)象緩存在DefaultSingletonBeanRegistry的singletonObjects 變量(ConcurrentHashMap類型)

類關(guān)系圖如下:

從類圖中看到DefaultListableBeanFactory實(shí)現(xiàn)了很多接口,spring 根據(jù)該類的功能定義了不同層次的接口。接口核心功能主要分兩類:1、AliasRegistry、BeanDefinitionRegistry接口主要提供BeanDefinition和alias注冊(cè)、獲取的方法,2、左半部分*BeanFactory相關(guān)接口、SingletonBeanRegistry接口提供對(duì)象的創(chuàng)建、緩存和獲取等方法

1.2、關(guān)鍵類之XmlBeanDefinitionReader

該類負(fù)責(zé)分析xml中bean的定義,并解析成BeanDefinition對(duì)象,然后調(diào)用DefaultListableBeanFactory的注冊(cè)方法緩存到DefaultListableBeanFactory中

1.3、關(guān)鍵類之ClassPathXmlApplicationContext

先上類關(guān)系圖:

這個(gè)就是spring上下文,是spring啟動(dòng)的入口類,從父類AbstractApplicationContext的refresh()方法中可以看出該類的主要功能:設(shè)置springContext.xml路徑、創(chuàng)建DefaultListableBeanFactory、提供對(duì)象創(chuàng)建過程中的各種擴(kuò)展點(diǎn)、事件的注冊(cè)和分發(fā)等等。

2、spring初始化過程中對(duì)外暴露的擴(kuò)展接口

1、BeanNameAware:void setBeanName(String name);

該bean獲取自己在DefaultListableBeanFactory中的id或name ,在spring框架里用的多,我們一般很少用到。

2、BeanFactoryAware:void setBeanFactory(BeanFactory beanFactory)

獲取創(chuàng)建該bean的DefaultListableBeanFactory對(duì)象,可以從該對(duì)象中回去bean對(duì)象,不過絕大多數(shù)時(shí)候我們是從ApplicationContext中來(lái)獲取。

3、ApplicationContextAware:void setApplicationContext(ApplicationContext applicationContext)

獲取該bean所屬的applicationContext,從而可以獲取到該上下文的bean對(duì)象。自己寫一個(gè)工具類實(shí)現(xiàn)該接口然后在配置文件中配置或加上@Component注解,通過這個(gè)工具類就很方便的在應(yīng)用中動(dòng)態(tài)獲取bean對(duì)象,這種工具類在很多老的項(xiàng)目中幾乎是一個(gè)標(biāo)配。

4、InitializingBean:void afterPropertiesSet()

spring提供兩中方式來(lái)對(duì)bean初始化后的擴(kuò)展,一種是實(shí)現(xiàn)InitializingBean接口,一種是使用通過init-method方法指定,spring初始化bean時(shí)在執(zhí)行InitializingBean接口的afterPropertiesSet方法后就緊接著執(zhí)行init-method指定的方法。使用init-method不會(huì)對(duì)spring產(chǎn)生依賴因此使用頻率較高,但由于這種方式使用反射方式來(lái)調(diào)用所以性能上低于直接調(diào)用 InitializingBean接口的afterPropertiesSet方法,后面會(huì)有相應(yīng)的代碼分析。

5、指定init-method

用的較多,可以理解為spring在bean對(duì)象初始化完后會(huì)通過反射的方式來(lái)執(zhí)行該bean中init-method指定的方法。通過在xml文件中的bean標(biāo)簽配置init-method或在該bean的方法上使用@PostConstruct注解達(dá)到效果。

6、BeanFactoryPostProcessor:void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)

從后面的代碼分析中我們發(fā)現(xiàn),實(shí)現(xiàn)BeanFactoryPostProcessor接口的bean的創(chuàng)建及接口方法的調(diào)用時(shí)間早于普通bean的創(chuàng)建。實(shí)現(xiàn)該接口可以拿到beanFactory對(duì)象,然后就看可以在普通bean對(duì)象創(chuàng)建之前進(jìn)行干預(yù)調(diào)整,PropertyPlaceholderConfigurer類大家應(yīng)該比較熟悉,該類實(shí)現(xiàn)BeanFactoryPostProcessor接口,在postProcessBeanFactory方法中將beanDefinitionMap中所有的BeanDefinition中的含有占位符的值修改為指定屬性文件中的值,這樣在創(chuàng)建對(duì)象的時(shí)候就能獲取到真實(shí)值。

7、BeanPostProcessor:Object postProcessBeforeInitialization(Object bean, String beanName);

     BeanPostProcessor:Object postProcessAfterInitialization(Object bean, String beanName);

該接口需要注意與BeanFactoryPostProcessor接口的區(qū)別:

BeanFactoryPostProcessor接口:A實(shí)現(xiàn)了該接口,spring啟動(dòng)的時(shí)候,在所有普通bean對(duì)象創(chuàng)建之前會(huì)先創(chuàng)建A對(duì)象并調(diào)用其postProcessBeanFactory方法,方法參數(shù)為beanFactory。

BeanPostProcessor接口:A實(shí)現(xiàn)了該接口,spring在創(chuàng)建普通的bean 對(duì)象B時(shí),在B對(duì)象初始化之前將B對(duì)象的實(shí)例和beanname作為入?yún)⒄{(diào)用A的前置方法postProcessBeforeInitialization,在B對(duì)象初始化之后將B對(duì)象的實(shí)例和beanname作為入?yún)⒄{(diào)用A的后置方法postProcessAfterInitialization。由此也可知實(shí)現(xiàn)該接口bean的創(chuàng)建時(shí)間早于普通bean的創(chuàng)建。

通過實(shí)現(xiàn)該接口也可以完成對(duì)bean對(duì)象的調(diào)整,但與BeanFactoryPostProcessor還是有本質(zhì)的區(qū)別,實(shí)現(xiàn)BeanFactoryPostProcessor可以理解為對(duì)創(chuàng)建的模板的調(diào)整,是對(duì)BeanDefinition對(duì)象的調(diào)整,而BeanPostProcessor則是在對(duì)象過程中做的臨時(shí)的調(diào)整,是對(duì)創(chuàng)建好的bean對(duì)象的調(diào)整

使用BeanPostProcessor需要注意:

①、前置、后置方法需要將修改后的bean對(duì)象返回這樣getbean時(shí)才能獲取到正確的bean對(duì)象

②、針對(duì)layz的bean對(duì)象創(chuàng)建則不會(huì)回調(diào)該接口的方法

8、ApplicationListener:void onApplicationEvent(E event)

spring上下文啟動(dòng)完成后回調(diào)該接口,比較常用。

3、擴(kuò)展點(diǎn)的啟動(dòng)順序

1、HelloWorldService bean對(duì)象

public class HelloWorldService implements BeanFactoryAware,BeanNameAware,BeanFactoryPostProcessor,
BeanPostProcessor,InitializingBean ,
ApplicationListener<ContextRefreshedEvent>,ApplicationContextAware {
    private String name;
    private AtomicInteger count = new AtomicInteger(1);
    private String getSeq(){
        return count.getAndIncrement()+"->";
    }
    public  HelloWorldService(){
        System.err.println(getSeq()+"HelloWorldService constructor");
    }
    public void initMethod(){
        System.err.println(getSeq()+"init method");
    }
    public void sayHello(){
        System.err.println(getSeq()+name+"say:hello,world");
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
    public void setBeanName(String name) {
        System.err.println(getSeq()+"BeanNameAware.setBeanName:"+name);
    }
 
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.err.println(getSeq()+"BeanFactoryAware.setBeanFactory:"+beanFactory);
    }
 
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.err.println(getSeq()+"ApplicationContextAware.setApplicationContext:->"+applicationContext);
    }
 
    public void afterPropertiesSet() {
        System.err.println(getSeq()+"InitializingBean.afterPropertiesSet");
    }
 
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        BeanDefinition beanDefinition = configurableListableBeanFactory.getBeanDefinition("peopleService");
        beanDefinition.getPropertyValues();
        MutablePropertyValues m = beanDefinition.getPropertyValues();
        m.addPropertyValue("content", "i am ok");
        System.err.println(getSeq()+"BeanFactoryPostProcessor.postProcessBeanFactory 將peopleService的content屬性修改為i am ok");
    }
 
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.err.println(getSeq()+"BeanPostProcessor.postProcessBeforeInitialization->"+beanName);
        return bean;
    }
 
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.err.println(getSeq()+"BeanPostProcessor.postProcessAfterInitialization->"+beanName);
        return bean;
    }
 
    public void onApplicationEvent(ContextRefreshedEvent event) {
        System.err.println(getSeq()+"ApplicationListener.onApplicationEvent: Refreshed->"+event.getApplicationContext());
    }
}

2 、非lazy的普通bean對(duì)象,PeopleService

public class PeopleService{
    private String content="";
    public PeopleService(){
        System.err.println("PeopleService constructor");
    }
    public void say(){
        System.err.println("PeopleService say:["+content+"]");
    }
 
    public String getContent() {
        return content;
    }
 
    public void setContent(String content) {
        this.content = content;
    }
}

3、啟動(dòng)類

public class AppMain {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        System.err.println("===============================================");
        HelloWorldService helloWorldService =  applicationContext.getBean("helloWorldService",HelloWorldService.class);
        helloWorldService.sayHello();
 
        PeopleService peopleService =  applicationContext.getBean("peopleService",PeopleService.class);
        peopleService.say();
    }
}

代碼執(zhí)行結(jié)果:

從輸入結(jié)果中我們得到以下信息:

1、HelloWorldService 實(shí)現(xiàn) BeanFactoryPostProcessor接口所以創(chuàng)建時(shí)間早于普通非lazy的bean對(duì)象PeopleService

2、1-7為HelloWorldService 創(chuàng)建過程輸出的日志,可以看到各擴(kuò)展接口的執(zhí)行順序

3、第7步之后開始創(chuàng)建PeopleService對(duì)象,創(chuàng)建過程中回調(diào)用HelloWorldService(實(shí)現(xiàn)了BeanPostProcessor接口) 的前置和后置方法

4、spring上下文啟動(dòng)完成后發(fā)布ContextRefreshedEvent事件,輸出第10步日志

spring初始化源碼淺析之代碼淺析》將從代碼來(lái)分析spring的初始化流程

總結(jié)

到此這篇關(guān)于spring初始化源碼之關(guān)鍵類和擴(kuò)展接口的文章就介紹到這了,更多相關(guān)spring初始化源碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java異常:異常處理--try-catch結(jié)構(gòu)詳解

    java異常:異常處理--try-catch結(jié)構(gòu)詳解

    今天小編就為大家分享一篇關(guān)于Java異常處理之try...catch...finally詳解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2021-09-09
  • Java Collections的emptyList、EMPTY_LIST詳解與使用說明

    Java Collections的emptyList、EMPTY_LIST詳解與使用說明

    這篇文章主要介紹了Java Collections的emptyList、EMPTY_LIST詳解與使用說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • spring4新特性之web開發(fā)增強(qiáng)

    spring4新特性之web開發(fā)增強(qiáng)

    這篇文章主要介紹了spring4新特性之web開發(fā)增強(qiáng)的相關(guān)資料,需要的朋友可以參考下
    2017-09-09
  • java中@JsonValue和@JsonCreator使用

    java中@JsonValue和@JsonCreator使用

    本文主要介紹了java中@JsonValue和@JsonCreator使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • Java實(shí)現(xiàn)百度AOI數(shù)據(jù)的解析與轉(zhuǎn)換

    Java實(shí)現(xiàn)百度AOI數(shù)據(jù)的解析與轉(zhuǎn)換

    Java作為一種成熟且廣泛應(yīng)用的編程語(yǔ)言,具有跨平臺(tái)、面向?qū)ο?、安全性高等特點(diǎn),非常適合用于開發(fā)各種類型的應(yīng)用程序,本文為大家整理了基于Java的AOI數(shù)據(jù)解析與轉(zhuǎn)換的實(shí)現(xiàn)方法,需要的可以參考下
    2025-02-02
  • IDEA如何自動(dòng)生成serialVersionUID的設(shè)置

    IDEA如何自動(dòng)生成serialVersionUID的設(shè)置

    這篇文章主要介紹了IDEA如何自動(dòng)生成 serialVersionUID 的設(shè)置,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • 通過java生成讀取二維碼詳解

    通過java生成讀取二維碼詳解

    這篇文章主要介紹了java二維碼生成讀取詳解,二維碼再生活在無(wú)處不在,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,下面和小編一起來(lái)學(xué)習(xí)一下吧
    2019-05-05
  • mybatis使用collection嵌套查詢的實(shí)現(xiàn)

    mybatis使用collection嵌套查詢的實(shí)現(xiàn)

    本文主要介紹了mybatis使用collection嵌套查詢的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • SpringBoot整合ShedLock解決定時(shí)任務(wù)防止重復(fù)執(zhí)行的問題

    SpringBoot整合ShedLock解決定時(shí)任務(wù)防止重復(fù)執(zhí)行的問題

    ShedLock是一個(gè)用于分布式系統(tǒng)中防止定時(shí)任務(wù)重復(fù)執(zhí)行的庫(kù),本文主要介紹了SpringBoot整合ShedLock解決定時(shí)任務(wù)防止重復(fù)執(zhí)行的問題,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-01-01
  • SpringBoot+Netty實(shí)現(xiàn)簡(jiǎn)單聊天室的示例代碼

    SpringBoot+Netty實(shí)現(xiàn)簡(jiǎn)單聊天室的示例代碼

    這篇文章主要介紹了如何利用SpringBoot Netty實(shí)現(xiàn)簡(jiǎn)單聊天室,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)SpringBoot有一定幫助,感興趣的同學(xué)可以了解一下
    2022-02-02

最新評(píng)論

昌图县| 博乐市| 高淳县| 梧州市| 曲松县| 张家口市| 米林县| 延庆县| 海口市| 邛崃市| 丰县| 大埔区| 云龙县| 光山县| 临泉县| 石柱| 万源市| 康保县| 南昌县| 兴海县| 武汉市| 江孜县| 天峻县| 友谊县| 灌云县| 海兴县| 肥乡县| 绿春县| 平原县| 许昌县| 吴川市| 汝南县| 台湾省| 开封县| 贵溪市| 谷城县| 蕲春县| 米泉市| 于都县| 昂仁县| 朔州市|