国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Spring(11) Bean的生命周期

這篇具有很好參考價值的文章主要介紹了Spring(11) Bean的生命周期。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

一、簡介

首先,為什么要學習 Spring 中 Bean 的生命周期呢?

雖然不了解 Bean 的生命周期,并不影響日常工作中的開發(fā)。但是如果我們了解了 Bean 的生命周期,可以幫助我們更好地掌握 Spring 框架,并且能夠讓我們更好地去理解 Spring 容器是如何管理和創(chuàng)建 Bean 示例的。如果以后遇到 Bean 的相關問題(比如 Spring 的循環(huán)依賴問題),就可以方便我們去調試和解決這些問題。同時也讓我們可以編寫出更健壯、靈活、易維護的應用程序。所以說,理解 Bean 的生命周期對掌握 Spring 框架來說是至關重要的。

這里我們主要分兩部分去說明:

  1. 先從整體上去介紹 Bean 創(chuàng)建的整個流程 -> Bean的流程;
  2. 然后再用代碼的方式去驗證流程 -> 代碼驗證。

二、Bean的流程

1.BeanDefinition

BeanDefinition:Bean 的定義信息。Spring 容器在進行實例化時,會將 xml 配置中 <bean> 的信息(注解也是如此)封裝成一個 BeanDefinition 對象,Spring 根據(jù) BeanDefinition 來創(chuàng)建 Bean 對象,里面有很多用來描述 Bean 的屬性。

有了 BeanDefinition 之后,再去創(chuàng)建 Bean 對象的時候,就可以通過反射去創(chuàng)建。

<bean id="userDao" class="com.demo.dao.impl.UserDaoImpl" lazy-init="true"/>
<bean id="userService" class="com.demo.service.UserServiceImpl" scope="singleton">
	<property name="userDao" ref="userDao"></property>
</bean>
Spring(11) Bean的生命周期,Spring,spring,java,后端
  • beanClassName:bean 的類名。
  • initMethodName:初始化方法名稱。
  • propertyValues:bean 的屬性值。
  • scope:作用域。
  • lazyInit:延遲初始化。

以上這些屬性都被封裝到 BeanDefinition 中備用。那具體什么時候用呢?這就是下面要說的 Bean 的生命周期。

2.Bean 的生命周期

目前我們已經有了 BeanDefinition 這個對象了,那第一步就是要去創(chuàng)建對象。

Spring(11) Bean的生命周期,Spring,spring,java,后端

  • 第1步,調用 Bean 的構造函數(shù)。 來去實例化當前 Bean 的對象。

  • 第2步,依賴注入。 像是一些 @Autowired 或者 @Value 標明的屬性,這些都是在依賴注入中完成。

  • 第3步,Aware接口。 比較常見的有三個,它們都是以 Aware 結尾的接口,如果 Bean 實現(xiàn)了這些接口,就要重寫里面的方法:

    BeanNameAware:在初始化過程中可以獲取到 Bean 的名稱。

    BeanFactoryAware:在初始化過程中可以獲取到 Bean 工廠。

    ApplicationContextAware:在初始化過程中可以獲取到應用上下文。

    以上這些內容都是為了方便對 Bean 進行擴展。

  • 第4步,BeanPostProcessor#before。 BeanPostProcessor 是 Bean 的后置處理器,用來增強 Bean 的功能的,在初始化方法調用之前(before)進行回調。這個 BeanPostProcessor 后置處理器在 Bean 的生命中其中占有非常重要的作用,需要重點記憶。

  • 第5步,調用初始化方法。 里面有兩部分:

    InitializingBean:這是一個接口類,如果當前 Bean 實現(xiàn)了這個接口的話,就要重寫里面的方法,這一步就是來執(zhí)行重寫之后的方法。

    自定義init方法:比如在 Bean 中的某一個方法使用了注解 @PostConstruct,這里就會去執(zhí)行標明了注解的方法。其實自定義init方法也是從 BeanDefinition 中讀取到的信息。

  • 第6步,BeanPostProcessor#after。 還是在 Bean 的后置處理器中執(zhí)行,但是是在初始化方法之后(after)執(zhí)行。在 Spring 中對 Bean 進行增強的話,都是用到這個初始化方法之后執(zhí)行的后置處理器。其實在 Spring 內部就使用到了很多的后置處理器,比較典型的就是:當一個類被曾倩了,使用到了 AOP,那這個類通常都是使用后置處理器(BeanPostProcessor#after)來增強的。我們知道 AOP 的底層使用的是動態(tài)代理,有兩種:JDK動態(tài)代理、CGLIB動態(tài)代理。

    到這一步之后,基本上這個對象就創(chuàng)建完成了,現(xiàn)在就可以從 Spring 容器中去獲取和使用這個 Bean 對象了。

    注意:依賴注入 開始到 BeanPostProcessor#after 完成之后,都是針對當前的 Bean 進行初始化賦值,當然也做了一些增強。這里需要注意,Spring 中 Bean 的創(chuàng)建是一步一步完成的,也就是說 Bean 的創(chuàng)建和初始化賦值是分開的。調用構造函數(shù)就是創(chuàng)建 Bean 對象,但是這里創(chuàng)建好后是一個空對象,里面沒有值,下面就是初始化賦值的過程。

  • 第6步,銷毀Bean。 當 Spring 容器關閉之后,這個 Bean 對象就要執(zhí)行銷毀的操作了。比較典型的是,如果在某個方法上使用了 @PreDestroy 這個注解,那這個方法就是一個銷毀的方法,Spring 容器關閉的時候就會執(zhí)行這個銷毀的方法。

以上就是 Bean 的生命周期,里面的步驟還是挺多的。為了方便加深印象,我們可以用代碼的方式去驗證一下。

三、代碼驗證

1.User 實體類

User.java

繼承了 BeanNameAware、BeanFactoryAwareApplicationContextAware、InitializingBean 接口。

package com.demo.lifecycle;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;

@Component
public class User implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean {

    public User() {
        System.out.println("User類的構造方法被調用了...");
    }

    /**
     * 姓名
     */
    private String name;

    @Value("張三")
    public void setName(String name) {
        System.out.println("setName方法被調用了...");
        this.name = name;
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("BeanNameAware接口的setBeanName方法被調用了,bean的名字是:" + name);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("BeanFactoryAware接口的setBeanFactory方法被調用了...");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("ApplicationContextAware接口的setApplicationContext方法被調用了...");
    }

    @Override
    public void afterPropertiesSet() {
        System.out.println("InitializingBean接口的afterPropertiesSet方法被調用了...");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("PreDestroy注解的destroy方法被調用了...");
    }
}

2.MyBeanPostProcessor 后置處理器

MyBeanPostProcessor.java

定義了 #before#after 方法的增強實現(xiàn)。

package com.demo.lifecycle;

import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.InvocationHandler;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Objects;

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        System.out.println("BeanPostProcessor接口的postProcessBeforeInitialization方法被調用了 -> user對象初始化方法前開始增強....");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        if (Objects.equals(beanName, "user")) {
            System.out.println("BeanPostProcessor接口的postProcessAfterInitialization方法被調用了 -> user對象初始化方法后開始增強....");
            // cglib代理對象
            /*Enhancer enhancer = new Enhancer();
            // 設置需要增強的類
            enhancer.setSuperclass(bean.getClass());
            // 執(zhí)行回調方法,增強方法
            enhancer.setCallback(new InvocationHandler() {
                @Override
                public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                    // 執(zhí)行目標方法
                    return method.invoke(bean, objects);
                }
            });
            // 創(chuàng)建代理對象
            return enhancer.create();*/
        }
        return bean;
    }
}

3.SpringConfig 掃描包配置

SpringConfig.java

配置了掃描包位置,只掃描 User 實體類和 MyBeanPostProcessor 后置處理器。

package com.demo.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.demo.lifecycle")
public class SpringConfig {
}

4.UserTest 測試類

UserTest.java

main 方法執(zhí)行,使用 SpringConfig 配置創(chuàng)建上下文,并從容器中獲取 user 的 Bean 對象。

package com.demo.test;

import com.demo.config.SpringConfig;
import com.demo.lifecycle.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class UserTest {

    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        User user = ctx.getBean(User.class);
        System.out.println(user);
    }
}

5.測試結果

由于我使用的是 SpringBoot 項目進行的測試,會多打印一些日志,其中不帶時間前綴的是我們手動 println 的日志。

Connected to the target VM, address: '127.0.0.1:61642', transport: 'socket'
20:03:56.949 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@9660f4e
20:03:56.985 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
20:03:57.100 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [D:\IdeaProjects\SpringBootExamples\springboot-demo\target\classes\com\demo\lifecycle\MyBeanPostProcessor.class]
20:03:57.105 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [D:\IdeaProjects\SpringBootExamples\springboot-demo\target\classes\com\demo\lifecycle\User.class]
20:03:57.266 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
20:03:57.270 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
20:03:57.272 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
20:03:57.275 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
20:03:57.281 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'myBeanPostProcessor'
20:03:57.304 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'springConfig'
BeanPostProcessor接口的postProcessBeforeInitialization方法被調用了 -> user對象初始化方法前開始增強....
20:03:57.305 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'user'
User類的構造方法被調用了...
setName方法被調用了...
BeanNameAware接口的setBeanName方法被調用了,bean的名字是:user
BeanFactoryAware接口的setBeanFactory方法被調用了...
ApplicationContextAware接口的setApplicationContext方法被調用了...
BeanPostProcessor接口的postProcessBeforeInitialization方法被調用了 -> user對象初始化方法前開始增強....
InitializingBean接口的afterPropertiesSet方法被調用了...
BeanPostProcessor接口的postProcessAfterInitialization方法被調用了 -> user對象初始化方法后開始增強....
User類的構造方法被調用了...
com.demo.lifecycle.User@2235eaab
Disconnected from the target VM, address: '127.0.0.1:61642', transport: 'socket'

Process finished with exit code 0

可以看到日志是按照我們梳理的 Bean 的生命周期順序打印的,驗證完畢。

6.模擬AOP增強

MyBeanPostProcessor.javapostProcessAfterInitialization() 方法中注釋了 AOP 底層 CGLIB 動態(tài)代理的演示代碼的,可以在 UserTestmain 方法中獲取到 user 的 Bean 對象后,將鼠標放到 user 上看下,打開和關閉 CGLIB 代理的注釋生成的 user Bean 會不同:

關閉 CGLIB 代理:

Spring(11) Bean的生命周期,Spring,spring,java,后端

打開 CGLIB 代理:

Spring(11) Bean的生命周期,Spring,spring,java,后端

三、總結

問: Spring 中 Bean 的生命周期是什么樣的?

答:

① 通過 BeanDefinition 獲取 Bean 的定義信息;
② 調用構造函數(shù)實例化 Bean;
③ Bean 的依賴注入;
④ 處理 Aware 接口(BeanNameAware、BeanFactoryAware、ApplicationContextAware);
⑤ Bean 的后置處理器 BeanPostProcessor-前置;
⑥ 初始化方法(InitializingBean、init-method);
⑦ Bean 的后置處理器 BeanPostProcessor-后置;
⑧ 銷毀 Bean。

整理完畢,完結撒花~ ??





參考地址:

1.框架篇-05-Spring-bean的生命周期,https://www.bilibili.com/video/BV1yT411H7YK/?p=39&spm_id_from=333.1007.top_right_bar_window_history.content.click&vd_source=cf16f2e5f7c4612add10f9f9268a2c8a文章來源地址http://www.zghlxwxcb.cn/news/detail-630032.html

到了這里,關于Spring(11) Bean的生命周期的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯(lián)網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 【Spring】Spring的Bean的生命周期

    【Spring】Spring的Bean的生命周期

    作者簡介:大家好,我是五度魚,一個普通的Java領域博主,不停輸出Java技術博客和干貨 。 座右銘:鍥而不舍,金石可鏤 。 個人主頁:五度魚學Java的主頁 在 Java 中, Bean 是一個重要的概念,它代表了應用程序中的一個對象。在開發(fā)中,我們經常使用 Bean 來管理對象的生命

    2024年01月16日
    瀏覽(35)
  • Spring整理-Spring Bean的生命周期

    Spring?Bean的生命周期涉及多個階段,從Bean的定義到其銷毀。在這個過程中,Spring容器負責創(chuàng)建、初始化、使用和最終銷毀Bean。了解這個生命周期有助于更好地管理Bean的行為和資源使用。 實例化(Instantiation): 容器首先創(chuàng)建Bean的實例。 填充屬性(Populate?Properties): 容器

    2024年01月21日
    瀏覽(31)
  • 【Spring】Bean的作用域與生命周期詳情:請簡述Spring的執(zhí)行流程并分析Bean的生命周期?

    【Spring】Bean的作用域與生命周期詳情:請簡述Spring的執(zhí)行流程并分析Bean的生命周期?

    ?我們都知道,Spring框架為開發(fā)人員提供了很多便捷,這使得開發(fā)人員能夠更加專注于應用程序的核心業(yè)務邏輯,而不需要花費大量時間和精力在技術細節(jié)上。作為一個包含眾多工具方法的IoC容器,存取JavaBean是其極為重要的一個環(huán)節(jié)。本文就對Spring中的Bean的作用域和生命周

    2024年02月12日
    瀏覽(27)
  • Spring Bean的生命周期

    Spring Bean的生命周期

    Bean生命周期的整個執(zhí)行過程描述如下: 1、根據(jù)配置情況調用Bean構造方法或工廠方法實例化 Bean。 2、利用依賴注入完成Bean中所有屬性值的配置注入。 3、如果Bean 實現(xiàn)了BeanNameAware 接口,則 Spring調用Bean的setBeanName()方法傳入當前Bean的id值。 4、如果Bean實現(xiàn)了BeanFactoryAware 接口

    2023年04月22日
    瀏覽(35)
  • Spring -- Bean的生命周期

    Spring -- Bean的生命周期

    Spring容器在進行實例化時,會將xml配置的bean的信息封裝成一個BeanDefinition對象,Spring根據(jù)BeanDefinition來創(chuàng)建Bean對象,里面有很多的屬性用來描述Bean? ?BeanDefinition 中幾個重要方法如下 beanClassName:bean 的類名 initMethodName:初始化方法名稱 properryValues:bean 的屬性值 scope:作用域

    2024年02月15日
    瀏覽(35)
  • Spring Bean的生命周期 -- Spring入門(三)

    Spring Bean的生命周期 -- Spring入門(三)

    為了鞏固所學的知識,作者嘗試著開始發(fā)布一些學習筆記類的博客,方便日后回顧。當然,如果能幫到一些萌新進行新技術的學習那也是極好的。作者菜菜一枚,文章中如果有記錄錯誤,歡迎讀者朋友們批評指正。 (博客的參考源碼以及可以在我主頁的資源里找到,如果在學

    2024年02月15日
    瀏覽(25)
  • 【Spring】Spring之Bean生命周期源碼解析

    什么是bean的生命周期 是指bean在spring中是如何生成,如何銷毀的; spring創(chuàng)建對象的過程,就是IOC(控制反轉)的過程; JFR Java Flight Record,java飛行記錄,類似于飛機的黑匣子,是JVM內置的基于事件的JDK監(jiān)控記錄框架,主要用于問題定位和持續(xù)監(jiān)控; 入口代碼: Spring啟動的時

    2024年02月15日
    瀏覽(23)
  • Spring中 Bean的生命周期

    Spring中 Bean的生命周期

    如果把Spring看做一個大型工廠,則Spring容器中的Bean就是該工廠的產品。要想使用這個工廠生產和管理Bean,就需要在配置文件中告訴它需要哪些Bean,以及需要使用何種方式將這些Bean裝配到一起。 Bean的本質就是Java中的類,而Spring中的Bean其實就是對實體類的引用,來生產Java類

    2024年01月24日
    瀏覽(24)
  • 詳解Spring Bean的生命周期

    詳解Spring Bean的生命周期

    Spring Bean的生命周期包括以下階段: 1. 實例化Bean 對于BeanFactory容器,當客戶向容器請求一個尚未初始化的bean時,或初始化bean的時候需要注入另一個尚未初始化的依賴時,容器就會調用createBean進行實例化。 對于ApplicationContext容器,當容器啟動結束后,便實例化所有的bean。

    2024年02月14日
    瀏覽(24)
  • Spring Bean的生命周期解讀

    Spring Bean的生命周期解讀

    目錄 ? 1. Spring IOC容器 1.1 Spring IOC 容器的設計 1.1.1 BeanFactory 1.1.2 ApplicationContext 1.2 Spring Bean的生命周期 1.2.1 BeanDefinition 1.2.2 InstantiationAwareBeanPostProcessor和BeanPostProcessor 1.2.3 測試生命周期 ? Spring IOC 容器的設計主要是基于 BeanFactory 和 ApplicationContex t兩個接口,其中ApplicationConte

    2024年02月11日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包