中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么深入了解Spring的Bean生命周期

發布時間:2022-01-11 14:30:59 來源:億速云 閱讀:126 作者:柒染 欄目:開發技術

本篇文章為大家展示了怎么深入了解Spring的Bean生命周期,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。


什么是 Spring Bean 的生命周期

對于普通的 Java 對象,當 new 的時候創建對象,然后該對象就能夠使用了。一旦該對象不再被使用,則由 Java 自動進行垃圾回收。

而 Spring 中的對象是 bean,bean 和普通的 Java 對象沒啥大的區別,只不過 Spring 不再自己去 new 對象了,而是由 IoC 容器去幫助我們實例化對象并且管理它,我們需要哪個對象,去問 IoC 容器要即可。IoC 其實就是解決對象之間的耦合問題,Spring Bean 的生命周期完全由容器控制。

Bean的生命周期

Spring bean的生命周期階段是:

怎么深入了解Spring的Bean生命周期

  • 1.bean定義:就是從xml或注解定位資源加載讀取bean的元信息并定義成一個BeanDefinition對象

  • 2.bean注冊:將BeanDefinition對象根據相應的規則放到緩存池map中

  • 3.實例化:根據BeanDefinition實例化真正的bean,即是調用構造函數

  • 4.依賴注入:屬性賦值調用setter方法,即是依賴注入(DI)

  • 5.初始化: 初始化是用戶能自定義擴展的階段

  • 6.銷毀: 銷毀是用戶能自定義擴展的階段

注:其他都是在這階段前后的擴展點

Spring角度查看bean的定義與注冊

怎么深入了解Spring的Bean生命周期

怎么深入了解Spring的Bean生命周期

refresh()

public void refresh() throws BeansException, IllegalStateException {
    synchronized(this.startupShutdownMonitor) {
        StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
         // 準備Bean初始化相關的環境信息,其內部提供了一個空實現的initPropertySources()方法用于提供給用戶一個更改相關環境信息的機會
        this.prepareRefresh();
        // 創建BeanFactory實例,并且注冊相關的bean信息
        ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
        // 注冊Aware和Processor實例,并且注冊了后續處理請求所需的一些Editor信息
        this.prepareBeanFactory(beanFactory);

        try {
            // 提供的一個空方法,用于供給子類對已經生成的BeanFactory的一些信息進行定制
            this.postProcessBeanFactory(beanFactory);
            StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
            // 調用BeanFactoryPostProcessor及其子接口的相關方法,這些接口提供了一個入口,提供給了調用方一個修改已經生成的BeanDefinition的入口
            this.invokeBeanFactoryPostProcessors(beanFactory);
            // 對BeanPostProcessor進行注冊
            this.registerBeanPostProcessors(beanFactory);
            beanPostProcess.end();
            // 初始化國際化所需的bean信息
            this.initMessageSource();
            // 初始化事件廣播器的bean信息
            this.initApplicationEventMulticaster();
            // 提供的一個空方法,供給子類用于提供自定義的bean信息,或者修改已有的bean信息
            this.onRefresh();
            // 注冊事件監聽器
            this.registerListeners();
             // 對已經注冊的非延遲(配置文件指定)bean的實例化
            this.finishBeanFactoryInitialization(beanFactory);
            // 清除緩存的資源信息,初始化一些聲明周期相關的bean,并且發布Context已被初始化的事件
            this.finishRefresh();
        } catch (BeansException var10) {
            if (this.logger.isWarnEnabled()) {
                this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
            }
             // 發生異常則銷毀已經生成的bean
            this.destroyBeans();
            // 重置refresh字段信息
            this.cancelRefresh(var10);
            throw var10;
        } finally {
            // 初始化一些緩存信息
            this.resetCommonCaches();
            contextRefresh.end();
        }

    }
}

怎么深入了解Spring的Bean生命周期

怎么深入了解Spring的Bean生命周期

怎么深入了解Spring的Bean生命周期

怎么深入了解Spring的Bean生命周期

怎么深入了解Spring的Bean生命周期

怎么深入了解Spring的Bean生命周期

怎么深入了解Spring的Bean生命周期

SpringBoot角度查看bean定義和注冊

怎么深入了解Spring的Bean生命周期

怎么深入了解Spring的Bean生命周期

怎么深入了解Spring的Bean生命周期

1. 自動加載配置類

怎么深入了解Spring的Bean生命周期

2. bean定義和注冊

怎么深入了解Spring的Bean生命周期

怎么深入了解Spring的Bean生命周期

注:springboot只是比spring多了自動配置相關流程,在spring上做了一層邏輯封裝。

實例化,依賴注入,初始化

AbstractAutowireCapableBeanFactory為AutowireCapableBeanFactory接口的一個實現類,其中AbstractAutowireCapableBeanFactory實現類的一個方法doCreateBean()

//位置:AbstractAutowireCapableBeanFactory#doCreateBean
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
    }

    if (instanceWrapper == null) {
    	// 實例化階段
        instanceWrapper = this.createBeanInstance(beanName, mbd, args);
    }

    ...

    Object exposedObject = bean;

    try {
    	// 依賴注入,屬性賦值階段
        this.populateBean(beanName, mbd, instanceWrapper);
        // 初始化階段
        exposedObject = this.initializeBean(beanName, exposedObject, mbd);
    } catch (Throwable var18) {
        ...
    }

    ...
}

可以發現,分別調用三種方法:

  • createBeanInstance() -> 實例化

  • populateBean() -> 依賴注入

  • initializeBean() -> 初始化

銷毀

銷毀階段是在容器關閉時調用的,在ConfigurableApplicationContext#close()

至于xxxAware,BeanPostProcessor,BeanFactoryPostProcessor等類,只不過是對主流程的一系列擴展點而已。

Bean的生命周期的擴展點

Spring Bean 的生命周期的擴展點很多,這里不可能全部列出來,只說核心的擴展點。這也就是為什么 Spring 的擴展性很好的原因,開了很多的口子,盡可能讓某個功能高內聚松耦合,用戶需要哪個功能就用哪個,而不是直接來一個大而全的東西。

Bean級別

這些接口的實現類是基于 Bean 的,只要實現了這些接口的Bean才起作用。

  • BeanNameAware

  • BeanFactoryAware

  • ApplicationContextAware

  • InitializingBean

  • DisposableBean

還要很多的xxxAware,這些不常用,下面生命周期測試就不加上,如:

  • BeanClassLoaderAware

  • EnvironmentAware

  • EmbeddedValueResolverAware

  • ResourceLoaderAware

  • ApplicationEventPublisherAware

  • MessageSourceAware

  • ServletContextAware

容器級別

這些接口的實現類是獨立于 Bean 的,并且會注冊到 Spring 容器中。一般稱它們的實現類為后置處理器。

在 Spring 容器創建任何 Bean 的時候,這些后置處理器都會發生作用

BeanPostProcessor

InstantiationAwareBeanPostProcessor(InstantiationAwareBeanPostProcessor 是繼承了 BeanPostProcessor)

工廠后處理器接口也是容器級的。在應用上下文裝配配置文件之后立即調用:

  • AspectJWeavingEnabler

  • ConfigurationClassPostProcessor

  • CustomAutowireConfigurer

常用接口

InstantiationAwareBeanPostProcessor

該類是 BeanPostProcessor 的子接口,常用的有如下三個方法:

  • postProcessBeforeInstantiation(Class beanClass, String beanName):在bean實例化之前調用

  • postProcessProperties(PropertyValues pvs, Object bean, String beanName):在bean實例化之后、設置屬性前調用

  • postProcessAfterInstantiation(Class beanClass, String beanName):在bean實例化之后調用

BeanNameAware

BeanNameAware接口是為了讓自身Bean能夠感知到,只有一個方法setBeanName(String name),獲取到自身在Spring容器中的id或name屬性。

BeanFactoryAware

該接口只有一個方法setBeanFactory(BeanFactory beanFactory),用來獲取當前環境中的 BeanFactory,可以對工廠中的所有bean進行擴展。

ApplicationContextAware

該接口只有一個方法setApplicationContext(ApplicationContext applicationContext),用來獲取當前環境中的 ApplicationContext,可以對整個容器進行擴展。

注:有時候并不會調用該接口,這要根據你的IOC容器來決定:Spring IOC容器最低要求是實現BeanFactory接口,而不是實現ApplicationContext接口,對于那些沒有實現ApplicationContext接口的容器,在生命周期對應的ApplicationContextAware定義的方法也是不會調用的,只要實現了ApplicationContext接口的容器,才會調用。

BeanPostProcessor

postProcessBeforeInitialization(Object bean, String beanName):在初始化之前調用此方法,Spring 的 AOP 就是利用它實現的。

postProcessAfterInitialization(Object bean, String beanName):在初始化之后調用此方法

InitializingBean

該接口只有一個方法afterPropertiesSet(),在屬性注入完成后調用。

凡是繼承該接口的類,在初始化bean的時候都會執行該方法,可以進行一些屬性配置等工作。

InitializingBean 對應生命周期的初始化階段,在源碼的invokeInitMethods(beanName, wrappedBean, mbd)方法中調用。

DisposableBean

該接口的作用是在對象銷毀時調用,可以做一些資源銷毀操作。

DisposableBean 類似于InitializingBean,對應生命周期的銷毀階段,以ConfigurableApplicationContext#close()方法作為入口,實現是通過循環取所有實現了DisposableBean接口的Bean然后調用其destroy()方法

常用注解

@Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")

@Bean聲明一個bean,配合@Configuration注解使用

initMethod:聲明bean初始化時回調一個方法,該方法需要程序員編寫

destroyMethod:聲明bean銷毀時回調一個方法,該方法需要程序員編寫

@PostConstruct

bean的一個基于注解的初始化方法

@PreDestroy

bean的一個基于注解的銷毀方法

案例分析

聲明一個bean

@Configuration
public class BeanInitAndDestroyConfig {

    /**
     * @return 這里沒有指定bean名字,默認是方法名
     */
    @Description("測試bean的生命周期")
    @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
    public MyService myServiceBeanName() {//入參數可注入其他依賴
        return new MyService();
    }
}
  • 聲明一個名為:myServiceBeanName的bean

  • initMethod:bean的初始化方法為:initMethod

  • destroyMethod:bean的銷毀方法為:destroyMethod

Animal實現類

怎么深入了解Spring的Bean生命周期

這里只是想用來說明 @Qualifier注解能根據bean名稱匹配。

我的服務類

即是針對當前bean只調用一次的接口

/**
 * @Description: bean生命周期測試:這些接口只針對當前bean
 * @Author: jianweil
 * @date: 2021/12/8 9:46
 */
public class MyService implements Person, BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {

    private Animal animal = null;

    private ApplicationContext applicationContext;

    /**
     *接口規定方法
     */
    @Override
    public void service() {
        this.animal.use();
    }

    public MyService() {
        System.out.println("2. [bean實例化]:"+this.getClass().getSimpleName()+"----------構造方法");
    }
    /**
     *接口規定方法:注入依賴
     */
    @Override
    @Autowired
    @Qualifier("dog")
    public void setAnimal(Animal animal) {
        System.out.println("5. [bean屬性賦值]:dog----依賴注入");
        this.animal = animal;
    }


    @Override
    public void setBeanName(String s) {
        System.out.println("6. 調用【BeanNameAware】--setBeanName:"+s);

    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("7. 調用【BeanFactoryAware】--setBeanFactory");
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        System.out.println("8. 調用【ApplicationContextAware】--setApplicationContext");

    }

    /**
     * 初始化1
     */
    @PostConstruct
    public void myInit() {
        System.out.println("10. [初始化] 注解@PostConstruct自定義初始化方法[myInit]");
    }

    /**
     * 初始化2
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("11. [初始化] 接口InitializingBean方法[afterPropertiesSet]");

    }

    /**
     * 初始化3
     */
    public void initMethod() {
        System.out.println("12. [初始化] 注解@Bean自定義初始化方法[initMethod]");
    }

    /**
     * 銷毀1
     */
    @PreDestroy
    public void myDestroy() {
        System.out.println("14. [銷毀] 注解@PreDestroy自定義銷毀方法[myDestroy]");
    }

    /**
     * 銷毀2
     */
    @Override
    public void destroy() throws Exception {
        System.out.println("15. [銷毀] 接口DisposableBean方法[destroy]");
    }

    /**
     * 銷毀3
     */
    public void destroyMethod() {
        System.out.println("16. [銷毀] 注解@Bean自定義銷毀方法[destroyMethod]");
    }
}

這里實現的接口只作用于當前bean(即是上面@bean定義的bean名為myDefineBeanName)生命周期

后置處理器

每個bean生命周期都執行一次

后置處理器是作用于ioc容器中所有bean的生命周期。

/**
 * @Description: todo
 * @Author: jianweil
 * @date: 2021/12/20 17:20
 */
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) {
            System.out.println("============================InstantiationAwareBeanPostProcessor-開始======================");
            System.out.println("1. [容器級別每個bean都回調] 調用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 方法:beanName為"+beanName);
        }
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) {
            System.out.println("3. [容器級別每個bean都回調] 調用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法:beanName為"+beanName);
        }
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) {
            System.out.println("4. [容器級別每個bean都回調] 調用 InstantiationAwareBeanPostProcessor.postProcessProperties() 方法:beanName為"+beanName);
            System.out.println("============================InstantiationAwareBeanPostProcessor-結束======================");

        }
        return null;
    }
}
/**
 * @Description: 后置bean的初始化器:所有的bean都會攔截執行
 * @Author: jianweil
 * @date: 2021/12/8 9:46
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        //這里過濾掉springboot自動配置的bean,只打印我們項目的bean情況
        if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) {
            System.out.println("9. [容器級別每個bean都回調] 調用 BeanPostProcessor.postProcessBeforeInitialization 方法:beanName為" + beanName);
        }

        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) {
            System.out.println("13. [容器級別每個bean都回調] 調用 BeanPostProcessor.postProcessAfterInitialization 方法:beanName為" + beanName);
        }
        return bean;
    }
}

工廠后置處理器

容器級別,只允許一次

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("0. [容器級別只調用一次] 調用 BeanFactoryPostProcessor.postProcessBeanFactory() 方法");
    }
}

輸出結果和結果解讀

“//”標記為解讀

//容器級別的工廠后置處理器,只在應用上下文裝配配置文件之后立即調用1次
0. [容器級別只調用一次] 調用 BeanFactoryPostProcessor.postProcessBeanFactory() 方法


//因為我們生命過程只打印("myServiceBeanName".equals(beanName) || "dog".equals(beanName)),所有貓只有構造方法打印了
貓----------構造方法

//###############################dog的生命周期###############################################
//后置處理器,容器級別,作用于所有bean
============================InstantiationAwareBeanPostProcessor-開始======================
1. [容器級別每個bean都回調] 調用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 方法:beanName為dog
//狗的實例化
狗----------構造方法
//后置處理器,容器級別,作用于所有bean
3. [容器級別每個bean都回調] 調用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法:beanName為dog
//后置處理器,容器級別,作用于所有bean
4. [容器級別每個bean都回調] 調用 InstantiationAwareBeanPostProcessor.postProcessProperties() 方法:beanName為dog
============================InstantiationAwareBeanPostProcessor-結束======================
//后置處理器,容器級別,作用于所有bean
9. [容器級別每個bean都回調] 調用 BeanPostProcessor.postProcessBeforeInitialization 方法:beanName為dog
//后置處理器,容器級別,作用于所有bean
13. [容器級別每個bean都回調] 調用 BeanPostProcessor.postProcessAfterInitialization 方法:beanName為dog
//###############################dog的bean完成,開始myServiceBeanName###############################################


//后置處理器,容器級別,作用于所有bean
============================InstantiationAwareBeanPostProcessor-開始======================
1. [容器級別每個bean都回調] 調用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 方法:beanName為myServiceBeanName

//實例化
2. [bean實例化]:MyService----------構造方法

//后置處理器,容器級別,作用于所有bean
3. [容器級別每個bean都回調] 調用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法:beanName為myServiceBeanName
//后置處理器,容器級別,作用于所有bean
4. [容器級別每個bean都回調] 調用 InstantiationAwareBeanPostProcessor.postProcessProperties() 方法:beanName為myServiceBeanName
============================InstantiationAwareBeanPostProcessor-結束======================

//屬性賦值,即是依賴注入
5. [bean屬性賦值]:dog----依賴注入

//bean級別,bean:myServiceBeanName實現了接口BeanNameAware
6. 調用【BeanNameAware】--setBeanName:myServiceBeanName
//bean級別
7. 調用【BeanFactoryAware】--setBeanFactory
//bean級別
8. 調用【ApplicationContextAware】--setApplicationContext

//后置處理器,容器級別,作用于所有bean:初始化前處理
9. [容器級別每個bean都回調] 調用 BeanPostProcessor.postProcessBeforeInitialization 方法:beanName為myServiceBeanName

//初始化
10. [初始化] 注解@PostConstruct自定義初始化方法[myInit]
11. [初始化] 接口InitializingBean方法[afterPropertiesSet]
12. [初始化] 注解@Bean自定義初始化方法[initMethod]

//后置處理器,容器級別,作用于所有bean:初始化后處理
13. [容器級別每個bean都回調] 調用 BeanPostProcessor.postProcessAfterInitialization 方法:beanName為myServiceBeanName

//容器環境加載完成,這時可以使用所有bean
2021-12-21 11:18:42.994  INFO 18956 --- [           main] c.l.s.SpringbootBeanLifecycleApplication : Started SpringbootBeanLifecycleApplication in 0.719 seconds (JVM running for 1.312)

//銷毀
14. [銷毀] 注解@PreDestroy自定義銷毀方法[myDestroy]
15. [銷毀] 接口DisposableBean方法[destroy]
16. [銷毀] 注解@Bean自定義銷毀方法[destroyMethod]

Process finished with exit code 0

Bean生命周期圖

怎么深入了解Spring的Bean生命周期

了解 Spring 生命周期的意義就在于,可以利用 Bean 在其存活期間的指定時刻完成一些相關操作。一般情況下,會在 Bean 被初始化后和被銷毀前執行一些相關操作。

上述內容就是怎么深入了解Spring的Bean生命周期,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

德兴市| 永定县| 余江县| 肇源县| 常熟市| 大安市| 连州市| 阿城市| 云浮市| 黄浦区| 武山县| 孟津县| 灵台县| 慈溪市| 九龙县| 铁岭市| 揭西县| 富宁县| 新民市| 内乡县| 基隆市| 靖宇县| 松滋市| 京山县| 潮安县| 汝城县| 大埔县| 雅江县| 南木林县| 吴桥县| 南昌市| 耒阳市| 西峡县| 岳西县| 长丰县| 昭苏县| 甘谷县| 晋江市| 盖州市| 三台县| 明溪县|