天天看點

Spring源碼--Bean生命周期

Spring源碼--Bean生命周期

  • ​​BeanNameAware​​
  • ​​BeanFactoryAware​​
  • ​​ApplicationContextAware​​
  • ​​postProcessBeforeInitialization​​
  • ​​@PostConstruct​​
  • ​​afterPropertiesSet​​
  • ​​postProcessAfterInitialization​​
  • ​​@PreDestory​​
  • ​​DisposableBean​​
  • ​​執行個體​​

先來一張bean的生命周期圖

Spring源碼--Bean生命周期

github位址:

​​https://github.com/a18792721831/studySpringSource.git​​

BeanNameAware

BeanNameAware的結構圖非常簡單

Spring源碼--Bean生命周期

其中Aware是一個标記性接口,内部沒有定義任何方法:

Spring源碼--Bean生命周期

通過其注釋就能看出來

Spring源碼--Bean生命周期

​BeanNameAware​

​​接口隻有一個方法:​

​setBeanName​

​設定bean的名字。

Spring源碼--Bean生命周期

說實話,我一開始對這個方法是一臉懵B的,這個方法有什麼用呢?

從名字和注釋上來看,貌似是設定這個bean的名字的。

但是仔細一想,不對啊,設定名字,不應該是參數為空,傳回值為String,這樣才能設定名字到BeanFactory中啊。

但是這方法剛好相反。

那麼就用反向思路來思考:這個方法不是設定bean的名字的,而是擷取bean的名字的。

結合spring的設計思想:普通的bean對于beanFactory是無感覺的,也就是說,作為一個普通的bean,我不知道誰會依賴我,也不會知道是誰管理我,我就是一個普通的bean。

換句話說,最為一個普通的社畜,隻要有活幹,有磚搬就行了。管他給誰搬磚,搬磚做什麼。

但是不能一輩子做一個社畜,人還是要有理想的。

作為一個bean,如果想知道自己在beanFactory中的名字,或者說代号,那麼就需要實作​

​BeanNameAware​

​的接口,這樣就表明了這個bean不是一個鹹魚,是一個有理想有抱負的bean,他想知道自己在beanFactory中的名字,不想做一個無名之士。

那麼spring容器在啟動的時候,發現這裡有一個有志向的bean,就會仁慈的将這個bean在beanFactory中的名字通過​

​setBeanName​

​方法告訴這個bean.

總結來說:這個方法是bean擷取自己在beanFactory中的名字。

BeanFactoryAware

​BeanFactoryAware​

​​和​

​BeanNameAware​

​​類似,結構非常簡單,都是繼承了标記性接口:​

​Aware​

​接口,然後實作一個方法:

Spring源碼--Bean生命周期

如果你了解了​

​BeanNameAware​

​接口的方法,那麼這個方法也非常容易了解。

作為bean,如果想知道自己在哪一個beanFactory中,就需要實作這個接口,然後容器就會将這個bean所在的beanFactory的BeanFactory告訴bean。

舉個例子哈:有些公司為了更加明确的區分業務,就會将原來一個完整公司,拆分成多個子公司,每個子公司負責一部分具體的業務。原公司裡面的人還是這麼多,甚至辦公的工位都沒有發生改變,但是已經是屬于不同的公司了。如果一個員工在拆分後想知道自己是哪一個分公司的,就需要發郵件問人力資源。

​setBeanFactory​

​就是人力資源将這個bean所在的beanFactory傳回給這個bean。

到了目前為止,這個bean已經和其他的bean有了明顯的不同了,這個bean已經知道了自己是誰,自己在哪了。

它還是一個鹹魚嗎?

ApplicationContextAware

非常有名的三個問題:你是誰,你在哪,你從哪裡來?

講過前面兩步,bean小兄弟已經知道了自己是誰,自己在哪,那麼,還剩下一個問題,就是bean存在的意義,從哪裡來。

​ApplicationContext​

​就是bean生活的範圍,是以,清晰的認知自己生活的範圍,就明白了自己存在的意義了。

Spring源碼--Bean生命周期

​ApplicationContextAware​

​的方法,就是告訴bean,運作時的上下文環境。

postProcessBeforeInitialization

預初始化操作,針對全部的bean生效。

Spring源碼--Bean生命周期

可以實作偷梁換柱。将預設的一個bean替換為其他的bean,以最終return的結果為主。

@PostConstruct

從Java EE5規範開始,Servlet中增加了兩個影響Servlet生命周期的注解,@PostConstruct和@PreDestroy,這兩個注解被用來修飾一個非靜态的void()方法。

Spring源碼--Bean生命周期

afterPropertiesSet

InitializingBean接口為bean提供了初始化方法的方式,它隻包括afterPropertiesSet方法,凡是繼承該接口的類,在初始化bean的時候都會執行該方法。

這個接口的方法是怎麼被調用的呢?

我們全盤搜尋一下:​

​instanceof InitializingBean​

Spring源碼--Bean生命周期

如果init-method和afterPropertiesSet同時配置,先執行afterPropertiesSet方法,然後執行init-method.

postProcessAfterInitialization

預初始化操作,針對全部的bean生效。

Spring源碼--Bean生命周期

@PreDestory

從Java EE5規範開始,Servlet中增加了兩個影響Servlet生命周期的注解,@PostConstruct和@PreDestroy,這兩個注解被用來修飾一個非靜态的void()方法。

Spring源碼--Bean生命周期

DisposableBean

對于實作了 DisposableBean 的 bean ,在spring釋放該bean後調用它的destroy() 方法。

Spring源碼--Bean生命周期

執行個體

建立一個bean

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * @author jiayq
 * @Date 2020-08-29
 */
@Component
public class People implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, BeanPostProcessor, InitializingBean, DisposableBean {

    public People() {
        System.out.println("1.create");
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("2.set bean name : " + name);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("3.set bean factory , name is " + beanFactory.getClass().getSimpleName());
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("4.set application context , name is " + applicationContext.getClass().getSimpleName() + " , id is " + applicationContext.getId());
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("5.post process before initialization , bean name is " + beanName);
        return bean;
    }

    @PostConstruct
    public void init() {
        System.out.println("6.post construct , this name is " + this.getClass().getSimpleName());
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("7.after properties set ");
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("8.post process after initializattion , bean name is " + beanName);
        return bean;
    }

    public void say() {
        System.out.println("9.normal survival");
    }

    @PreDestroy
    public void destory() {
        System.out.println("10.pre destory");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("11.destroy by DisposableBean");
    }
}      

main類

import com.study.source.beans.People;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

@SpringBootApplication
public class SourceApplication {

    public static void main(String[] args) {
//        ConfigurableApplicationContext context = SpringApplication.run(SourceApplication.class, args);
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.study.source");
        People bean = context.getBean(People.class);
        bean.say();
        context.close();
    }
}      

輸出結果:

Spring源碼--Bean生命周期
Spring源碼--Bean生命周期

檢視下​

​AnnotationConfigApplicationContext​

​的調用鍊

Spring源碼--Bean生命周期

繼續閱讀