Spring IOC 源碼解析

Spring IOC 源碼解析

此文章部分轉載自其餘資源,畢竟不能竊讀人家的成果,我只是在分享本身所學到的.html

控制反轉(IoC)

控制反轉(IoC)原理的Spring Framework實現。IoC也稱爲依賴注入(DI)。這是一個過程,經過這個過程,對象只能經過構造函數參數,工廠方法的參數或在構造或從工廠方法返回後在對象實例上設置的屬性來定義它們的依賴關係(即,它們使用的其餘對象)。 。而後容器在建立bean時注入這些依賴項。此過程基本上是bean自己的逆(所以名稱,控制反轉),經過使用類的直接構造或諸如服務定位器模式的機制來控制其依賴關係的實例化或位置。(官方文檔5.x說明)。所謂IoC,對於spring框架來講,就是由spring來負責控制對象的生命週期和對象間的關係。java

基於XML的元數據不是惟一容許的配置元數據形式。Spring IoC容器自己徹底與實際編寫此配置元數據的格式分離。目前,許多開發人員爲其Spring應用程序選擇 基於Java的配置面試

有關在Spring容器中使用其餘形式的元數據的信息,請參閱:spring

  • 基於註釋的配置:Spring 2.5引入了對基於註釋的配置元數據的支持。(我這裏不解釋)
  • 基於Java的配置:從Spring 3.0開始,Spring JavaConfig項目提供的許多功能成爲核心Spring Framework的一部分。所以,您可使用Java而不是XML文件在應用程序類外部定義bean。要使用這些新功能,請參閱 @Configuration, @Bean, @Import,和@DependsOn註釋。

首先了解什麼是spring Bean?spring的bean是具備完整的spring生命週期的對象。數組

那spring生命週期的經歷了什麼呢?bash

初始化、屬性賦值、實例化、銷燬。數據結構

spring容器能夠稱爲spring上下文或者spring環境。app

spring容器包含各類組件,如:bean工廠、單例池、讀取器、掃描器、處理器、後置處理器等框架

這裏將會解釋一下:ide

bean的初始化和實例化:

bean的初始化:一個對象被new出來,完成屬性方法填充,最後生命週期回調方法執行

bean的實例化:一個類變成bean的過程

Spring的生命週期

Spring的9個後置處理器

流傳的大部分博客對spring生命週期的見解

不知道Spring官方對Bean的生命問題是否有明確的定義或者解析,可是Spring In Action以及市面上流傳的大部分博客是這樣的:

  1. 實例化Bean對象,這個時候Bean的對象是很是低級的,基本不可以被咱們使用,由於連最基本的屬性都沒有設置,能夠理解爲連Autowired註解都是沒有解析的;
  2. 填充屬性,當作完這一步,Bean對象基本是完整的了,能夠理解爲Autowired註解已經解析完畢,依賴注入完成了;
  3. 若是Bean實現了BeanNameAware接口,則調用setBeanName方法;
  4. 若是Bean實現了BeanClassLoaderAware接口,則調用setBeanClassLoader方法;
  5. 若是Bean實現了BeanFactoryAware接口,則調用setBeanFactory方法;
  6. 調用BeanPostProcessor的postProcessBeforeInitialization方法;
  7. 若是Bean實現了InitializingBean接口,調用afterPropertiesSet方法;
  8. 若是Bean定義了init-method方法,則調用Bean的init-method方法;
  9. 調用BeanPostProcessor的postProcessAfterInitialization方法;當進行到這一步,Bean已經被準備就緒了,一直停留在應用的上下文中,直到被銷燬;
  10. 若是應用的上下文被銷燬了,若是Bean實現了DisposableBean接口,則調用destroy方法,若是Bean定義了destory-method聲明瞭銷燬方法也會被調用。

基於Java的配置

從這裏出發:

AnnotationConfigApplicationContext context=
    new AnnotationConfigApplicationContext(AppConfig.class);
複製代碼

AnnotationConfigApplicationContext的結構關係:

建立AnnotationConfigApplicationContext對象

//根據參數類型能夠知道,其實能夠傳入多個annotatedClasses,可是這種狀況出現的比較少
    public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
        //調用無參構造函數,會先調用父類GenericApplicationContext的構造函數
        //父類的構造函數裏面就是初始化DefaultListableBeanFactory,而且賦值給beanFactory
        //本類的構造函數裏面,初始化了一個讀取器:AnnotatedBeanDefinitionReader read,一個掃描器ClassPathBeanDefinitionScanner scanner
        //scanner的用處不是很大,它僅僅是在咱們外部手動調用 .scan 等方法纔有用,常規方式是不會用到scanner對象的
        this();
        //把傳入的類進行註冊,這裏有兩個狀況,
        //傳入傳統的配置類
        //傳入bean(雖然通常沒有人會這麼作
        //看到後面會知道spring把傳統的帶上@Configuration的配置類稱之爲FULL配置類,不帶@Configuration的稱之爲Lite配置類
        //可是咱們這裏先把帶上@Configuration的配置類稱之爲傳統配置類,不帶的稱之爲普通bean
        register(annotatedClasses);
        //刷新
        refresh();
    }
複製代碼

咱們先來爲構造方法作一個簡單的說明:

  1. 這是一個有參的構造方法,能夠接收多個配置類,不過通常狀況下,只會傳入一個配置類。
  2. 這個配置類有兩種狀況,一種是傳統意義上的帶上@Configuration註解的配置類,還有一種是沒有帶上@Configuration,可是帶有@Component,@Import,@ImportResouce,@Service,@ComponentScan等註解的配置類,在Spring內部把前者稱爲Full配置類,把後者稱之爲Lite配置類。在本源碼分析中,有些地方也把Lite配置類稱爲普通Bean

使用斷點調試,經過this()調用此類無參的構造方法,代碼到下面:

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {

    //註解bean定義讀取器,主要做用是用來讀取被註解的了bean
    private final AnnotatedBeanDefinitionReader reader;

    //掃描器,它僅僅是在咱們外部手動調用 .scan 等方法纔有用,常規方式是不會用到scanner對象的
    private final ClassPathBeanDefinitionScanner scanner;

    /** * Create a new AnnotationConfigApplicationContext that needs to be populated * through {@link #register} calls and then manually {@linkplain #refresh refreshed}. */
    public AnnotationConfigApplicationContext() {
        //會隱式調用父類的構造方法,初始化DefaultListableBeanFactory

        //初始化一個Bean讀取器
        this.reader = new AnnotatedBeanDefinitionReader(this);

        //初始化一個掃描器,它僅僅是在咱們外部手動調用 .scan 等方法纔有用,常規方式是不會用到scanner對象的
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }
}
複製代碼

首先無參構造方法中就是對讀取器reader和掃描器scanner進行了實例化,reader的類型是AnnotatedBeanDefinitionReader,能夠看出它是一個 「打了註解的Bean定義讀取器」,scanner的類型是ClassPathBeanDefinitionScanner,它僅僅是在外面手動調用.scan方法,或者調用參數爲String的構造方法,傳入須要掃描的包名纔會用到,像這樣方式傳入的配置類是不會用到這個scanner對象的。

AnnotationConfigApplicationContext類是有繼承關係的,會隱式調用父類的構造方法:

下面代碼,初始化DefaultListableBeanFactory

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {

    private final DefaultListableBeanFactory beanFactory;

    @Nullable
    private ResourceLoader resourceLoader;

    private boolean customClassLoader = false;

    private final AtomicBoolean refreshed = new AtomicBoolean();


    /** * Create a new GenericApplicationContext. * @see #registerBeanDefinition * @see #refresh */
    public GenericApplicationContext() {
        this.beanFactory = new DefaultListableBeanFactory();
    }
}
複製代碼

DefaultListableBeanFactory的關係圖

DefaultListableBeanFactory是至關重要的,從字面意思就能夠看出它是一個Bean的工廠,什麼是Bean的工廠?固然就是用來生產和得到Bean的。

讓咱們把目光回到AnnotationConfigApplicationContext的無參構造方法,讓咱們看看Spring在初始化AnnotatedBeanDefinitionReader的時候作了什麼:

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
        this(registry, getOrCreateEnvironment(registry));
    }
複製代碼

這裏的BeanDefinitionRegistry固然就是AnnotationConfigApplicationContext的實例了,這裏又直接調用了此類其餘的構造方法:

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        Assert.notNull(environment, "Environment must not be null");
        this.registry = registry;
        this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }
複製代碼

讓咱們把目光移動到這個方法的最後一行,進入registerAnnotationConfigProcessors方法:

public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
        registerAnnotationConfigProcessors(registry, null);
    }
複製代碼

這又是一個門面方法,再點進去,這個方法的返回值Set,可是上游方法並無去接收這個返回值,因此這個方法的返回值也不是很重要了,固然方法內部給這個返回值賦值也不重要了。因爲這個方法內容比較多,這裏就把最核心的貼出來,這個方法的核心就是註冊Spring內置的多個Bean:

if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
複製代碼
  1. 判斷容器中是否已經存在了ConfigurationClassPostProcessor Bean
  2. 若是不存在(固然這裏確定是不存在的),就經過RootBeanDefinition的構造方法得到ConfigurationClassPostProcessorBeanDefinitionRootBeanDefinitionBeanDefinition的子類:
  3. 執行registerPostProcessor方法,registerPostProcessor方法內部就是註冊Bean,固然這裏註冊其餘Bean也是同樣的流程。

BeanDefinition是什麼?

BeanDefinition聯繫圖

它是用來描述Bean的,裏面存放着關於Bean的一系列信息,好比Bean的做用域,Bean所對應的Class,是否懶加載,是否Primary等等,這個BeanDefinition也至關重要,咱們之後會經常和它打交道。**

registerPostProcessor方法:

private static BeanDefinitionHolder registerPostProcessor( BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {

        definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        registry.registerBeanDefinition(beanName, definition);
        return new BeanDefinitionHolder(definition, beanName);
    }

複製代碼

這方法爲BeanDefinition設置了一個Role,ROLE_INFRASTRUCTURE表明這是spring內部的,並不是用戶定義的,而後又調用了registerBeanDefinition方法,再點進去,Oh No,你會發現它是一個接口,沒辦法直接點進去了,首先要知道registry實現類是什麼,那麼它的實現是什麼呢?答案是DefaultListableBeanFactory:

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
        this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
    }

複製代碼

這又是一個門面方法,再點進去,核心在於下面兩行代碼:

//beanDefinitionMap是Map<String, BeanDefinition>,
//這裏就是把beanName做爲key,ScopedProxyMode做爲value,推到map裏面
this.beanDefinitionMap.put(beanName, beanDefinition);

//beanDefinitionNames就是一個List<String>,這裏就是把beanName放到List中去
this.beanDefinitionNames.add(beanName);

複製代碼

從這裏能夠看出DefaultListableBeanFactory就是咱們所說的容器了,裏面放着beanDefinitionMap,beanDefinitionNames,beanDefinitionMap是一個hashMap,beanName做爲Key,beanDefinition做爲Value,beanDefinitionNames是一個集合,裏面存放了beanName。打個斷點,第一次運行到這裏,監視這兩個變量:

DefaultListableBeanFactory中的beanDefinitionMap,beanDefinitionNames也是至關重要的,之後會常常看到它,最好看到它,第一時間就能夠反應出它裏面放了什麼數據

這裏僅僅是註冊,能夠簡單的理解爲把一些原料放入工廠,工廠尚未真正的去生產。

上面已經介紹過,這裏會一連串註冊好幾個Bean,在這其中最重要的一個Bean(沒有之一)就是BeanDefinitionRegistryPostProcessor Bean。

ConfigurationClassPostProcessor實現BeanDefinitionRegistryPostProcessor接口,BeanDefinitionRegistryPostProcessor接口又擴展了BeanFactoryPostProcessor接口,BeanFactoryPostProcessor是Spring的擴展點之一,ConfigurationClassPostProcessor是Spring極爲重要的一個類,必須緊緊的記住上面所說的這個類和它的繼承關係。

除了註冊了ConfigurationClassPostProcessor,還註冊了其餘Bean,其餘Bean也都實現了其餘接口,好比BeanPostProcessor等。

BeanPostProcessor接口也是Spring的擴展點之一。

至此,實例化AnnotatedBeanDefinitionReader reader分析完畢。

因爲常規使用方式是不會用到AnnotationConfigApplicationContext裏面的scanner的,因此這裏就不看scanner是如何被實例化的了。

把目光回到最開始,再分析第二行代碼:

register(annotatedClasses);

複製代碼

這裏傳進去的是一個數組,最終會循環調用以下方法:

<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
        //AnnotatedGenericBeanDefinition能夠理解爲一種數據結構,是用來描述Bean的,這裏的做用就是把傳入的標記了註解的類
        //轉爲AnnotatedGenericBeanDefinition數據結構,裏面有一個getMetadata方法,能夠拿到類上的註解
        AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);

        //判斷是否須要跳過註解,spring中有一個@Condition註解,當不知足條件,這個bean就不會被解析
        if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
            return;
        }

        abd.setInstanceSupplier(instanceSupplier);

        //解析bean的做用域,若是沒有設置的話,默認爲單例
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
        abd.setScope(scopeMetadata.getScopeName());

        //得到beanName
        String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

        //解析通用註解,填充到AnnotatedGenericBeanDefinition,解析的註解爲Lazy,Primary,DependsOn,Role,Description
        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

        //限定符處理,不是特指@Qualifier註解,也有多是Primary,或者是Lazy,或者是其餘(理論上是任何註解,這裏沒有判斷註解的有效性),若是咱們在外面,以相似這種
        //AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Appconfig.class);常規方式去初始化spring,
        //qualifiers永遠都是空的,包括上面的name和instanceSupplier都是一樣的道理
        //可是spring提供了其餘方式去註冊bean,就可能會傳入了
        if (qualifiers != null) {
            //能夠傳入qualifier數組,因此須要循環處理
            for (Class<? extends Annotation> qualifier : qualifiers) {
                //Primary註解優先
                if (Primary.class == qualifier) {
                    abd.setPrimary(true);
                }
                //Lazy註解
                else if (Lazy.class == qualifier) {
                    abd.setLazyInit(true);
                }
                //其餘,AnnotatedGenericBeanDefinition有個Map<String,AutowireCandidateQualifier>屬性,直接push進去
                else {
                    abd.addQualifier(new AutowireCandidateQualifier(qualifier));
                }
            }
        }

        for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
            customizer.customize(abd);
        }

        //這個方法用處不大,就是把AnnotatedGenericBeanDefinition數據結構和beanName封裝到一個對象中
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);

        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

        //註冊,最終會調用DefaultListableBeanFactory中的registerBeanDefinition方法去註冊,
        //DefaultListableBeanFactory維護着一系列信息,好比beanDefinitionNames,beanDefinitionMap
        //beanDefinitionNames是一個List<String>,用來保存beanName
        //beanDefinitionMap是一個Map,用來保存beanName和beanDefinition
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }

複製代碼

在這裏又要說明下,以常規方式去註冊配置類,此方法中除了第一個參數,其餘參數都是默認值。

  1. 經過AnnotatedGenericBeanDefinition的構造方法,得到配置類的BeanDefinition,這裏是否是似曾類似,在註冊ConfigurationClassPostProcessor類的時候,也是經過構造方法去得到BeanDefinition的,只不過當時是經過RootBeanDefinition去得到,如今是經過AnnotatedGenericBeanDefinition去得到。

    image.png

  2. 判斷需不須要跳過註冊,Spring中有一個@Condition註解,若是不知足條件,就會跳過這個類的註冊。

  3. 而後是解析做用域,若是沒有設置的話,默認爲單例。

  4. 得到BeanName。

  5. 解析通用註解,填充到AnnotatedGenericBeanDefinition,解析的註解爲Lazy,Primary,DependsOn,Role,Description。

  6. 限定符處理,不是特指@Qualifier註解,也有多是Primary,或者是Lazy,或者是其餘(理論上是任何註解,這裏沒有判斷註解的有效性)。

  7. 把AnnotatedGenericBeanDefinition數據結構和beanName封裝到一個對象中(這個不是很重要,能夠簡單的理解爲方便傳參)。

  8. 註冊,最終會調用DefaultListableBeanFactory中的registerBeanDefinition方法去註冊:

public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {

        //獲取beanName
        // Register bean definition under primary name.
        String beanName = definitionHolder.getBeanName();

        //註冊bean
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

                //Spring支持別名
        // Register aliases for bean name, if any.
        String[] aliases = definitionHolder.getAliases();
        if (aliases != null) {
            for (String alias : aliases) {
                registry.registerAlias(beanName, alias);
            }
        }
    }

複製代碼

這個registerBeanDefinition是否是又有一種似曾類似的感受,沒錯,在上面註冊Spring內置的Bean的時候,已經解析過這個方法了,這裏就不重複了,此時,讓咱們再觀察下beanDefinitionMap beanDefinitionNames兩個變量,除了Spring內置的Bean,還有咱們傳進來的Bean,這裏的Bean固然就是咱們的配置類了:

image.png
image.png

到這裏註冊配置類也分析完畢了。

你們能夠看到其實到這裏,Spring尚未進行掃描,只是實例化了一個工廠,註冊了一些內置的Bean和咱們傳進去的配置類,真正的大頭是在第三行代碼:

refresh();

複製代碼

爲了驗證上面的邏輯,能夠作個試驗:

首先定義了一個Bean,裏面有各類回調,其中須要注意下,我在SpringBean的構造方法中打印了studentService,看SpringBean被new的出來的時候,studentService是否被注入了;又在setBeanName中打印了studentService,看此時studentService是否被注入了,以此來驗證,Bean是什麼時候完成的自動注入的(這個StudentServiceImpl 類的代碼就不貼出來了,無非就是一個最普通的Bean):

public class SpringBean implements InitializingBean, DisposableBean, BeanNameAware, BeanFactoryAware, BeanClassLoaderAware {

    public SpringBean() {
        System.out.println("SpringBean構造方法:" + studentService);
        System.out.println("SpringBean構造方法");
    }

    @Autowired
    StudentServiceImpl studentService;

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

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

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("setBeanClassLoader");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("setBeanFactory");
    }

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

    public void initMethod() {
        System.out.println("initMethod");
    }

    public void destroyMethod() {
        System.out.println("destroyMethod");
    }
}

複製代碼

再定義一個BeanPostProcessor,在重寫的兩個方法中進行了判斷,若是傳進來的beanName是springBean才進行打印:

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(beanName.equals("springBean")) {
            System.out.println("postProcessBeforeInitialization");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(beanName.equals("springBean")) {
            System.out.println("postProcessAfterInitialization");
        }
        return bean;
    }
}

複製代碼

定義一個配置類,完成自動掃描,可是SpringBean是手動註冊的,而且聲明瞭initMethod和destroyMethod:

@Configuration
@ComponentScan
public class AppConfig {
    @Bean(initMethod = "initMethod",destroyMethod = "destroyMethod")
    public SpringBean springBean() {
        return new SpringBean();
    }
}

複製代碼

最後就是啓動類了:

public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext =
                new AnnotationConfigApplicationContext(AppConfig.class);
        annotationConfigApplicationContext.destroy();
    }

複製代碼

運行結果:

SpringBean構造方法:null
SpringBean構造方法
setBeanName:com.codebear.StudentServiceImpl@31190526
setBeanName
setBeanClassLoader
setBeanFactory
postProcessBeforeInitialization
afterPropertiesSet
initMethod
postProcessAfterInitialization
destroy
destroyMethod

複製代碼

能夠看到,試驗結果和上面分析的徹底一致。

這就是廣爲流傳的Spring生命週期。

也許你在應付面試的時候,是死記硬背這些結論的,如今我帶着你找到這些方法,跟我來。

首先咱們來到AnnotationConfigApplicationContext的構造方法:

//根據參數類型能夠知道,其實能夠傳入多個annotatedClasses,可是這種狀況出現的比較少
    public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
        //調用無參構造函數,會先調用父類GenericApplicationContext的構造函數
        //父類的構造函數裏面就是初始化DefaultListableBeanFactory,而且賦值給beanFactory
        //本類的構造函數裏面,初始化了一個讀取器:AnnotatedBeanDefinitionReader read,一個掃描器ClassPathBeanDefinitionScanner scanner
        //scanner的用處不是很大,它僅僅是在咱們外部手動調用 .scan 等方法纔有用,常規方式是不會用到scanner對象的
        this();
        //把傳入的類進行註冊,這裏有兩個狀況,
        //傳入傳統的配置類
        //傳入bean(雖然通常沒有人會這麼作
        //看到後面會知道spring把傳統的帶上@Configuration的配置類稱之爲FULL配置類,不帶@Configuration的稱之爲Lite配置類
        //可是咱們這裏先把帶上@Configuration的配置類稱之爲傳統配置類,不帶的稱之爲普通bean
        register(annotatedClasses);
        //刷新
        refresh();
    }

複製代碼

進入refresh方法,refresh方法中有一個finishBeanFactoryInitialization小方法,這個方法是用來實例化懶加載單例Bean的,也就是咱們的Bean都是在這裏被建立出來的(固然我這裏說的的是絕大部分狀況是這樣的):

finishBeanFactoryInitialization(beanFactory);

複製代碼

咱們再進入finishBeanFactoryInitialization這方法,裏面有一個beanFactory.preInstantiateSingletons()方法:

//初始化全部的非懶加載單例
        beanFactory.preInstantiateSingletons();

複製代碼

咱們嘗試再點進去,這個時候你會發現這是一個接口,好在它只有一個實現類,因此能夠咱們來到了他的惟一實現,實現類就是org.springframework.beans.factory.support.DefaultListableBeanFactory,這裏面是一個循環,咱們的Bean就是循環被建立出來的,咱們找到其中的getBean方法:

getBean(beanName);

複製代碼

這裏有一個分支,若是Bean是FactoryBean,如何如何,若是Bean不是FactoryBean如何如何,好在不論是不是FactoryBean,最終仍是會調用getBean方法,因此咱們能夠堅決果斷的點進去,點進去以後,你會發現,這是一個門面方法,直接調用了doGetBean方法:

return doGetBean(name, null, null, false);

複製代碼

再進去,不斷的深刻,接近咱們要尋找的東西。 這裏面的比較複雜,可是有我在,我能夠直接告訴你,下一步咱們要進入哪裏,咱們要進入

if (mbd.isSingleton()) {

                    //getSingleton中的第二個參數類型是ObjectFactory<?>,是一個函數式接口,不會馬上執行,而是在
                    //getSingleton方法中,調用ObjectFactory的getObject,纔會執行createBean
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

複製代碼

這裏面的createBean方法,再點進去啊,可是又點不進去了,這是接口啊,可是別慌,這個接口又只有一個實現類,因此說 沒事,就是幹,這個實現類爲org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory。

這個實現的方法裏面又作了不少事情,咱們就不去看了,我就是帶着你們找到那幾個生命週期的回調到底定義在哪裏就OK了。

Object beanInstance = doCreateBean(beanName, mbdToUse, args);//建立bean,核心
            if (logger.isDebugEnabled()) {
                logger.debug("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;

複製代碼

再繼續深刻doCreateBean方法,這個方法又作了一堆一堆的事情,可是值得開心的事情就是 咱們已經找到了咱們要尋找的東西了。

建立實例

首先是建立實例,位於:

instanceWrapper = createBeanInstance(beanName, mbd, args);//建立bean的實例。核心

複製代碼

填充屬性

其次是填充屬性,位於:

populateBean(beanName, mbd, instanceWrapper);//填充屬性,炒雞重要

複製代碼

在填充屬性下面有一行代碼:

exposedObject = initializeBean(beanName, exposedObject, mbd);

複製代碼

繼續深刻進去。

aware系列接口的回調

aware系列接口的回調位於initializeBean中的invokeAwareMethods方法:

invokeAwareMethods(beanName, bean);
private void invokeAwareMethods(final String beanName, final Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof BeanNameAware) {
                ((BeanNameAware) bean).setBeanName(beanName);
            }
            if (bean instanceof BeanClassLoaderAware) {
                ClassLoader bcl = getBeanClassLoader();
                if (bcl != null) {
                    ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
                }
            }
            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
            }
        }
    }

複製代碼

BeanPostProcessor的postProcessBeforeInitialization方法

BeanPostProcessor的postProcessBeforeInitialization方法位於initializeBean的

if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }
    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {

        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessBeforeInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }

複製代碼

afterPropertiesSet init-method

afterPropertiesSet init-method位於initializeBean中的

invokeInitMethods(beanName, wrappedBean, mbd);

複製代碼

這裏面調用了兩個方法,一個是afterPropertiesSet方法,一個是init-method方法:

((InitializingBean) bean).afterPropertiesSet();
invokeCustomInitMethod(beanName, bean, mbd);

複製代碼

BeanPostProcessor的postProcessAfterInitialization方法

BeanPostProcessor的postProcessAfterInitialization方法位於initializeBean的

if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {

        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }

複製代碼

固然在實際的開發中,應該沒人會去銷燬Spring的應用上下文把,因此剩餘的兩個銷燬的回調就不去找了。

這就是廣爲流傳的Spring Bean的生命週期,我也帶着你們找到了各類回調和鉤子,可是我認爲這並不是是Spring Bean完整的生命週期,只是通過簡化的,那麼我認爲的完整的生命週期是如何的呢,請聽下回分解。

相關文章
相關標籤/搜索