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

Spring Bean的生命周期解讀

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

目錄

?文章來源地址http://www.zghlxwxcb.cn/news/detail-511777.html

1. Spring IOC容器

1.1 Spring IOC 容器的設(shè)計

1.1.1 BeanFactory

1.1.2 ApplicationContext

1.2 Spring Bean的生命周期

1.2.1 BeanDefinition

1.2.2 InstantiationAwareBeanPostProcessor和BeanPostProcessor

1.2.3 測試生命周期


?

1. Spring IOC容器

1.1 Spring IOC 容器的設(shè)計

Spring IOC 容器的設(shè)計主要是基于BeanFactoryApplicationContext兩個接口,其中ApplicationContext是BeanFactory的子接口之一,換句話說BeanFactory是Spring IOC容器所定義的最頂層接口,而ApplicationContext是其高級接口之一,并且對于BeanFactory功能做了許多有用的擴展,所以在絕大部分的工作場景中,都會使用ApplicationContext作為Spring IOC 容器,如下圖所示:

Spring Bean的生命周期解讀

?首先我們定義一個User實體類:

public class User {
    String username;
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                '}';
    }
}

1.1.1 BeanFactory

BeanFactory的使用注冊Bean對象以及獲取Bean對象代碼如下:

DefaultListableBeanFactory beanFactory=new DefaultListableBeanFactory();
        RootBeanDefinition rootBeanDefinition=new RootBeanDefinition(User.class);
        beanFactory.registerBeanDefinition("user",rootBeanDefinition);
        System.out.println(beanFactory.getBean("user",User.class));

1.1.2 ApplicationContext

ApplicationContext的使用注冊Bean對象以及獲取Bean對象代碼如下:

 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.register(User.class);
        applicationContext.refresh();
        System.out.println(applicationContext.getBean("user", User.class));

1.2 Spring Bean的生命周期

Spring 容器可以管理 singleton 作用域 Bean 的生命周期,在此作用域下,Spring 能夠精確地知道該 Bean 何時被創(chuàng)建,何時初始化完成,以及何時被銷毀。

而對于 prototype 作用域的 Bean,Spring 只負責(zé)創(chuàng)建,當(dāng)容器創(chuàng)建了 Bean 的實例后,Bean 的實例就交給客戶端代碼管理,Spring 容器將不再跟蹤其生命周期。每次客戶端請求 prototype 作用域的 Bean 時,Spring 容器都會創(chuàng)建一個新的實例,并且不會管那些被配置成 prototype 作用域的 Bean 的生命周期。

生命周期主要是為了了解Spring IOC容器初始化和銷毀Bean的過程,通過對它的學(xué)習(xí)就可以知道如何在初始化和銷毀的時候加入自定義的方法,以滿足特定的需求。如下圖:

Spring Bean的生命周期解讀

?

從上圖可以看到,Spring IoC容器對Bean 的管理還是比較復(fù)雜的,Spring loC容器在執(zhí)行了初始化和依賴注入后,會執(zhí)行一定的步驟來完成初始化,通過這些步驟我們就能自定義初始化,而在Spring IoC 容器正常關(guān)閉的時候,它也會執(zhí)行一定的步驟來關(guān)閉容器,釋放資源。除需要了解整個生命周期的步驟外,還要知道這些生命周期的接口是針對什么而言的,首先介紹生命周期的步驟。

1.?如果 Bean 實現(xiàn)了接口 BeanNameAware的setBeanName方法,那么它就會調(diào)用這個方法。
2.?如果 Bean 實現(xiàn)了接口 BeanFactoryAware 的 setBeanFactory方法,那么它就會調(diào)用這個方法。
3.?如果 Bean實現(xiàn)了接口 ApplicationContextAware 的 setApplicationContext方法,且
Spring loC容器也必須是一個ApplicationContext 接口的實現(xiàn)類,那么才會調(diào)用這個方法,否則是不調(diào)用的。
4.?如果 Bean 實現(xiàn)了接口 BeanPostProcessor 的 postProcessBeforeInitialization方法,那么它就會調(diào)用這個方法。

5 .如果 Bean實現(xiàn)了接口BeanFactoryPostProcessor的afterPropertiesSet方法,那么它就會調(diào)用這個方法。
6.?如果 Bean自定義了初始化方法,它就會調(diào)用已定義的初始化方法。
7.?如果Bean 實現(xiàn)了接口 BeanPostProcessor 的postProcessAfterInitialization方法,完成了這些調(diào)用,這個時候Bean 就完成了初始化,那么 Bean就生存在Spring loC的容器中了,使用者就可以從中獲取 Bean的服務(wù)。
8.?當(dāng)服務(wù)器正常關(guān)閉,或者遇到其他關(guān)閉 Spring loC 容器的事件,它就會調(diào)用對應(yīng)的方完成Bean 的銷毀,其步驟如下:
? ? ? ? 如果Bean實現(xiàn)了接口 DisposableBean 的 destroy方法,那么就會調(diào)用它。
? ? ? ? 如果定義了自定義的銷毀方法,那么就會調(diào)用它。

1.2.1 BeanDefinition

Spring容器啟動的過程中,會將Bean解析成Spring內(nèi)部的BeanDefinition結(jié)構(gòu)。不管是是通過xml配置文件的<Bean>標(biāo)簽,還是通過注解配置的@Bean,還是@Compontent標(biāo)注的類,還是掃描得到的類,它最終都會被解析成一個BeanDefinition對象,最后我們的Bean工廠就會根據(jù)這份Bean的定義信息,對bean進行實例化、初始化等等操作。

你可以把BeanDefinition丟給Bean工廠,然后Bean工廠就會根據(jù)這個信息幫你生產(chǎn)一個Bean實例,拿去使用。

BeanDefinition里面里面包含了bean定義的各種信息,如:bean對應(yīng)的class、scope、lazy信息、dependOn信息、autowireCandidate(是否是候選對象)、primary(是否是主要的候選者)等信息。

Spring Bean的生命周期解讀

?RootBeanDefinition類:表示根bean定義信息,通常bean中沒有父bean的就使用這種表示。

ChildBeanDefinition類:表示子bean定義信息,如果需要指定父bean的,可以使用ChildBeanDefinition來定義子bean的配置信息,里面有parentName屬性,用來指定父bean的名稱。

GenericBeanDefinition類:通用的bean定義信息,既可以表示沒有父bean的bean配置信息,也可以表示有父bean的子bean配置信息,這個類里面也有parentName屬性,用來指定父bean的名稱。

ConfigurationClassBeanDefinition類:表示通過配置類中@Bean方法定義bean信息

可以通過配置類中使用@Bean來標(biāo)注一些方法,通過這些方法來定義bean,這些方法配置的bean信息最后會轉(zhuǎn)換為ConfigurationClassBeanDefinition類型的對象。

AnnotatedBeanDefinition接口:表示通過注解的方式定義的bean信息。

BeanDefinitionBuilder:構(gòu)建BeanDefinition的工具類

1.2.2 InstantiationAwareBeanPostProcessor和BeanPostProcessor

?

InstantiationAwareBeanPostProcessor實際上繼承了BeanPostProcessor接口。InstantiationAwareBeanPostProcessor作用于實例化階段的前后,BeanPostProcessor作用于初始化階段的前后。如下圖:

Spring Bean的生命周期解讀

?BeanPostProcessor是一個接口,還有很多子接口,這些接口中提供了很多方法,spring在bean生命周期的不同階段,會調(diào)用BeanPostProcessor中的一些方法,來對生命周期進行擴展,bean生命周期中的所有擴展點都是依靠這個集合中的BeanPostProcessor來實現(xiàn)的。該接口提供了兩個函數(shù):postProcessBeforeInitialzation( Object bean, String beanName ) 當(dāng)前正在初始化的bean對象會被傳遞進來,我們就可以對這個bean作任何處理。 這個函數(shù)會先于InitialzationBean執(zhí)行,因此稱為前置處理。 所有Aware接口的注入就是在這一步完成的。postProcessAfterInitialzation( Object bean, String beanName ) 當(dāng)前正在初始化的bean對象會被傳遞進來,我們就可以對這個bean作任何處理。 這個函數(shù)會在InitialzationBean完成后執(zhí)行,因此稱為后置處理。


Spring Aware是Spring定義的回調(diào)接口。何為回調(diào)?就是客戶程序C調(diào)用服務(wù)程序S中的某個函數(shù)A,然后S又在某個時候反過來調(diào)用C中的某個函數(shù)B,對于C來說,這個B便叫做回調(diào)函數(shù)。

1.2.3 測試生命周期

我們自定義一個User實體類,要求Spring容器使用我們自定義的@MyAutowired注解標(biāo)注的構(gòu)造方法進行構(gòu)造Bean對象,然后我們觀察在Bean周期的日志打印,更好的理解Bean周期過程。

自定義@MyAutowired注解

@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target(ElementType.CONSTRUCTOR)
public @interface MyAutowired {
}

定義User實體類

public class User implements InitializingBean, DisposableBean {
    String username;
    //Spring為了降低對客戶代碼的侵入性,給bean的配置提供了init-method屬性,
    // 該屬性指定了在這一階段需要執(zhí)行的函數(shù)名。Spring便會在初始化階段執(zhí)行我們設(shè)置的函數(shù)。
    // init-method本質(zhì)上仍然使用了InitializingBean接口。
    public void init(){
        System.out.println(this.getClass().getSimpleName()+" 執(zhí)行自定義初始化方法");
    }

    public User() {
    }

    @MyAutowired
    public User(String username) {
        this.username = username;
    }


    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                '}';
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("調(diào)用DisposableBean接口的destroy方法");
    }
    //afterPropertiesSet()這一階段也可以在bean正式構(gòu)造完成前增加我們自定義的邏輯,
    // 但它與前置處理不同,由于該函數(shù)并不會把當(dāng)前bean對象傳進來,因此在這一步?jīng)]辦法處理對象本身,
    // 只能增加一些額外的邏輯。 若要使用它,我們需要讓bean實現(xiàn)該接口,把要增加的邏輯寫在該函數(shù)中。
    // 然后Spring會在前置處理完成后檢測當(dāng)前bean是否實現(xiàn)了該接口,并執(zhí)行afterPropertiesSet函數(shù)
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("調(diào)用afterPropertiesSet方法");
    }
}

測試代碼

public class MyTest {
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory=new DefaultListableBeanFactory();
        //InstantiationAwareBeanPostProcessor接口在Bean對象實例化前的方法
        beanFactory.addBeanPostProcessor(new InstantiationAwareBeanPostProcessor() {
            public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
                if(beanName.equals("user"))
                System.out.println(beanName+" Bean對象在實例化之前操作**");
                return null;
            }
        });
        //InstantiationAwareBeanPostProcessor接口在Bean對象實例化后的方法
        beanFactory.addBeanPostProcessor(new InstantiationAwareBeanPostProcessor() {
            public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
                if(beanName.equals("user"))
                System.out.println(beanName+" Bean對象在實例化之后操作**");
                return false;
            }
        });
        //使用自己自定義含有@MyAutowired注解的構(gòu)造方法,實例化Bean對象
        beanFactory.addBeanPostProcessor(new SmartInstantiationAwareBeanPostProcessor() {
            public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
                if(beanName.equals("user"))
                System.out.println("實例化Bean對象");
                Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors();
                List<Constructor<?>> collect = Arrays.stream(declaredConstructors).filter(i -> i.isAnnotationPresent(MyAutowired.class)).collect(Collectors.toList());
                Constructor[] constructors = collect.toArray(new Constructor[collect.size()]);
                return constructors.length>0?constructors:null;

            }
        });
        //BeanPostProcessor接口在Bean對象初始化之前的方法調(diào)用
        beanFactory.addBeanPostProcessor(new BeanPostProcessor() {
            @Override
            public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
                if(beanName.equals("user"))
                    System.out.println(beanName+" Bean對象在初始化之前操作**");
                return null;
            }
        });
       //BeanPostProcessor接口在Bean對象初始化之后的方法調(diào)用
        beanFactory.addBeanPostProcessor(new BeanPostProcessor() {
            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                if(beanName.equals("user"))
                    System.out.println(beanName+" Bean對象在初始化之后操作**");
                return null;
            }
        });

        RootBeanDefinition rootBeanDefinition= (RootBeanDefinition) BeanDefinitionBuilder.rootBeanDefinition(User.class).setInitMethodName("init").getBeanDefinition();
        beanFactory.registerBeanDefinition("user",rootBeanDefinition);
        beanFactory.registerBeanDefinition("username", BeanDefinitionBuilder.genericBeanDefinition(String.class)
                .addConstructorArgValue("admin").getBeanDefinition());
        System.out.println(beanFactory.getBean("user",User.class));
        beanFactory.destroySingletons();


    }
}

測試截圖

Spring Bean的生命周期解讀

至此這篇文章到此結(jié)束。

Spring Bean的生命周期解讀

?

?

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

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

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 【spring】spring bean的生命周期

    【spring】spring bean的生命周期

    spring bean的生命周期 簡介 本文測試并且介紹了spring中bean的生命周期,如果只想知道結(jié)果可以跳到最后一部分直接查看。 一、bean的創(chuàng)建階段 spring中的bean是何時創(chuàng)建的? 在spring中有一個非常重要的注解,叫做**@Scope**,這個注解是用來控制spring中的bean是否是單例的,一般情況

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

    Spring Bean的生命周期

    Bean生命周期的整個執(zhí)行過程描述如下: 1、根據(jù)配置情況調(diào)用Bean構(gòu)造方法或工廠方法實例化 Bean。 2、利用依賴注入完成Bean中所有屬性值的配置注入。 3、如果Bean 實現(xiàn)了BeanNameAware 接口,則 Spring調(diào)用Bean的setBeanName()方法傳入當(dāng)前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整理-Spring Bean的生命周期

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

    2024年01月21日
    瀏覽(32)
  • 【Spring】Spring的Bean的生命周期

    【Spring】Spring的Bean的生命周期

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

    2024年01月16日
    瀏覽(36)
  • Spring中 Bean的生命周期

    Spring中 Bean的生命周期

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

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

    詳解Spring Bean的生命周期

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

    2024年02月14日
    瀏覽(24)
  • Spring源碼:Bean生命周期(五)

    在上一篇文章中,我們深入探討了 Spring 框架中 Bean 的實例化過程,該過程包括從 Bean 定義中加載當(dāng)前類、尋找所有實現(xiàn)了 InstantiationAwareBeanPostProcessor 接口的類并調(diào)用實例化前的方法、進行實例化、調(diào)用 applyMergedBeanDefinitionPostProcessors 方法等多個步驟,最終生成了一個真正的

    2024年02月04日
    瀏覽(21)
  • Spring(11) Bean的生命周期

    Spring(11) Bean的生命周期

    首先,為什么要學(xué)習(xí) Spring 中 Bean 的生命周期呢? 雖然不了解 Bean 的生命周期,并不影響日常工作中的開發(fā)。但是如果我們了解了 Bean 的生命周期,可以幫助我們更好地掌握 Spring 框架,并且能夠讓我們更好地去理解 Spring 容器是如何管理和創(chuàng)建 Bean 示例的。如果以后遇到 B

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

    在您的應(yīng)用程序中,由 Spring IoC 容器管理的形成其核心的對象被稱為 \\\"bean\\\" 。一個 bean 是由 Spring IoC 容器實例化、組裝和管理的對象 這些 bean 是通過您提供給容器的配置元數(shù)據(jù)創(chuàng)建的。 Bean 定義包含了所謂的配置元數(shù)據(jù),容器需要了解以下內(nèi)容: 如何創(chuàng)建一個 bean Bean 的生命

    2024年02月09日
    瀏覽(28)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包