Spring源碼分析專題系列(3)「IOC容器初始化」徹底讓你明白和理解運(yùn)行原理和源碼流程

前言介紹

本篇文章篇幅較大,希望讀者可以慢慢閱讀,建議收藏悬垃,分多次閱讀學(xué)習(xí)游昼。

  • 學(xué)習(xí)源碼的過程當(dāng)中,有幾點(diǎn)建議:

    • 一定要學(xué)會抓重點(diǎn)尝蠕,歸納核心類烘豌、核心方法、核心步驟看彼;

    • 分析源碼我們不需要太過于糾結(jié)細(xì)節(jié)廊佩,不然,這個源碼最起碼得分析月才能分析完靖榕;

    • 主要的目的是分析整個容器初始化過程标锄,怎么初始化bean,怎么設(shè)置動態(tài)代理茁计;我們主要學(xué)習(xí)的是他們的思想料皇,以及代碼中運(yùn)用到的設(shè)計(jì)模式

容器框架重要對象

  • BeanFactory:用于訪問容器中bean的接口星压,使用的是工廠模式践剂,重點(diǎn)注意DefaultListableBeanFactory,是貫穿的整個容器的基本工廠類租幕。

  • BeanDefinition:BeanDefinition是bean在Spring中的描述舷手,先讀取到bean的各種元素,然后利用BeanDefinition去初始化bean劲绪,是spring從起管理bean對象的數(shù)據(jù)模型。

  • BeanDefinitionRegistry接口:注冊bean定義到Spring容器中盆赤,與BeanFactory接口相對應(yīng)贾富,主要針對于Bean的注冊,BeanFactory主要針對于bean對象的管理牺六。

  • BeanFactoryPostProcessor接口:bean工廠后置處理器颤枪,該接口的作用主要是提供擴(kuò)展點(diǎn),用于各種bean定義的注冊和實(shí)例化等淑际,比較需要主要關(guān)注ConfigurationClassPostProcessor該類畏纲;

  • BeanPostProcessor接口:bean的后置處理器,該接口提供的擴(kuò)展點(diǎn)春缕,用于初始化bean盗胀,以及初始化完成后的各種擴(kuò)展

IOC容器初始化的大致流程

  • 首先讀取BeanDefinition放到容器中锄贼。

  • 通過BeanFactoryPostProcessor對象的擴(kuò)展

  • 通過BeanPostProcessor對象的擴(kuò)展

  • 然后根據(jù)BeanDefinition去初始化bean票灰。

  • 最后實(shí)際進(jìn)行初始化然后保存到容器中。

image
image

來實(shí)現(xiàn)各種不同的功能;IOC容器初始化大致的一個流程屑迂,主要是看AnnotationConfigApplicationContextrefresh

AnnotationConfigApplicationContext構(gòu)造器分析

傳入配置類的構(gòu)造函數(shù)

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    //初始化容器浸策,創(chuàng)建bean工廠,加載各種內(nèi)部重要類的bean定義惹盼,用于初始化我們或者其他引入類
    this();
    //注冊我們配置類的bean定義庸汗,初始化容器,從這個類開始
    register(componentClasses);
    //準(zhǔn)備工作做好后手报,開始初始化容器
    refresh();
}

先看下this()這一行代碼

AnnotatedBeanDefinitionReader:主要用于讀取相關(guān)內(nèi)部的Spring容器的Bean對象夫晌。

public AnnotationConfigApplicationContext() {
    //初始化讀取bean定義的讀取器,完成Spring內(nèi)部bean定義的注冊
    this.reader = new AnnotatedBeanDefinitionReader(this);
    //初始化一個類掃描器昧诱,其實(shí)這個方法進(jìn)來晓淀,是沒有用到這個掃描器的
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

從上面創(chuàng)建bean定義讀取器,看下構(gòu)造方法

//從上面創(chuàng)建bean定義讀取器盏档,看下構(gòu)造方法
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
    this(registry, getOrCreateEnvironment(registry));
}

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    Assert.notNull(environment, "Environment must not be null");
    //把ApplicationContext對象賦值給bean定義讀取器
    this.registry = registry;
    this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
    //主要是看這個方法凶掰,注冊Spring內(nèi)部重要的bean定義
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

到這里this(),這個方法流程就過完了蜈亩,主要就是注冊spring內(nèi)部重要的bean定義懦窘,來看下register(componentClasses)方法

//此目的主要針對于上面注冊的reader進(jìn)行注冊相關(guān)的bean
public void register(Class<?>... annotatedClasses) {
    Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
    //使用上面初始化的bean定義讀取器,去注冊我們配置類的bean定義
    this.reader.register(annotatedClasses);
}
//遍歷去注冊傳入進(jìn)來的注解相關(guān)的Bean對象
public void register(Class<?>... annotatedClasses) {
    for (Class<?> annotatedClass : annotatedClasses) {
        registerBean(annotatedClass);
    }
}
// 
public void registerBean(Class<?> annotatedClass) {
    doRegisterBean(annotatedClass, null, null, null);
}
//注冊bean定義
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
        @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
        @Nullable BeanDefinitionCustomizer[] customizers) {
    //根據(jù)配置類創(chuàng)建一個bean定義
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
    if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
        return;
    }
    abd.setInstanceSupplier(supplier);
    //解析bean的作用域稚配,如果沒有設(shè)置畅涂,則默認(rèn)是單例
    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
    abd.setScope(scopeMetadata.getScopeName());
    // 創(chuàng)建bean對象的bean名稱
    String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
    //解析該bean是否有Lazy,Primary道川,DependsOn午衰,Description等注解,有則填充進(jìn)去
    AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
    if (qualifiers != null) {
        for (Class<? extends Annotation> qualifier : qualifiers) {
            //判斷是否是Primary
            if (Primary.class == qualifier) {
                abd.setPrimary(true);
            }
            // 判斷是否屬于懶惰加載
            else if (Lazy.class == qualifier) {
                abd.setLazyInit(true);
            }
            else {
                abd.addQualifier(new AutowireCandidateQualifier(qualifier));
            }
        }
    }
    if (customizers != null) {
        for (BeanDefinitionCustomizer customizer : customizers) {
            customizer.customize(abd);
        }
    }
    // 構(gòu)建BeanDefinitionHolder對象去引用對象
    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    //最后把該bean定義注冊到Bean工廠中去
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

register(componentClasses)冒萄,方法到此結(jié)束臊岸,然后我們分析refresh();方法,該方法初始化了IOC容器尊流。

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        //設(shè)置容器狀態(tài)帅戒,準(zhǔn)備刷新容器
        prepareRefresh();
        //獲取到容器的bean工廠
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        //填充bean工廠的各種屬性
        prepareBeanFactory(beanFactory);
        try {
            //留給子類實(shí)現(xiàn),我們看的AnnotationConfigApplicationContext繼承了GenericApplicationContext崖技,該類主要是注冊了ServletContextAwareProcessor
            postProcessBeanFactory(beanFactory);
            //主要調(diào)用bean工廠的后置處理器逻住,把我們的類,注冊成bean定義
            invokeBeanFactoryPostProcessors(beanFactory);
              // 注冊 BeanPostProcessor 的實(shí)現(xiàn)類
         // 此接口兩個方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
         // 兩個方法分別在 Bean 初始化之前和初始化之后得到執(zhí)行迎献。注意瞎访,到這里 Bean 還沒初始化
            registerBeanPostProcessors(beanFactory);
            //初始化國際化資源(這個方法不重要)
            initMessageSource();
            //Spring事件相關(guān),主要是創(chuàng)建一個事件多播器
            initApplicationEventMulticaster();
            //留給子類實(shí)現(xiàn)
            onRefresh();
            //把我們的事件注冊到容器中
            registerListeners();
            //實(shí)例化我們需要的bean忿晕,放入IOC容器
            finishBeanFactoryInitialization(beanFactory);
            //完成容器IOC容器初始化装诡,并且發(fā)布初始化完成事件
            finishRefresh();
        }
        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                        "cancelling refresh attempt: " + ex);
            }
            destroyBeans();
            cancelRefresh(ex);
            throw ex;
        }
        finally {
            resetCommonCaches();
        }
    }
}

分析主要的步驟

  1. 首先 prepareRefresh():方法主要是為容器設(shè)置一個狀態(tài)(準(zhǔn)備工作银受,記錄下容器的啟動時間、標(biāo)記“已啟動”狀態(tài)鸦采、處理配置文件中的占位符)
  2. 然后接下來是獲取相應(yīng)的工廠類宾巍,AnnotationConfigApplicationContext主要是獲取到DefaultListableBeanFactory,但是如果是XML方式渔伯,會在該方法去加載bean定義顶霞,我們不分析這種方式
    • 這步比較關(guān)鍵,這步完成后锣吼,配置文件/配置類就會解析成一個Bean定義选浑,注冊到 BeanFactory 中,
    • 這里說的Bean還沒有初始化玄叠,只是配置信息都提取出來了古徒,
    • 注冊也只是將這些信息都保存到了注冊中心(說到底核心是一個 beanName-> beanDefinition 的 map)
prepareRefresh() 創(chuàng)建容器前的準(zhǔn)備工作
protected void prepareRefresh() {
   // 記錄啟動時間砰识,
   // 將 active 屬性設(shè)置為 true撑刺,closed 屬性設(shè)置為 false,它們都是 AtomicBoolean 類型
   this.startupDate = System.currentTimeMillis();
   this.closed.set(false);
   this.active.set(true);
   if (logger.isInfoEnabled()) {
      logger.info("Refreshing " + this);
   }
   // Initialize any placeholder property sources in the context environment
   initPropertySources();
   // 校驗(yàn) xml 配置文件
   getEnvironment().validateRequiredProperties();
   this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}

obtainFreshBeanFactory() 創(chuàng)建 Bean 容器述呐,加載并注冊 Bean
IoC初始化里面最重要的部分寺惫。

關(guān)鍵是以下幾步:

  • 初始化BeanFactory
  • 加載Bean
  • 注冊Bean

注意:這步完成后疹吃,Bean 并沒有完成初始化,實(shí)際的實(shí)例并沒有被創(chuàng)建西雀。

AbstractApplicationContext#obtainFreshBeanFactory()

   protected ConfigurableListableBeanFactory obtainFreshBeanFactory(){
        // 關(guān)閉舊的 BeanFactory (如果有)萨驶,創(chuàng)建新的 BeanFactory,加載 Bean 定義艇肴、注冊 Bean 等等
        refreshBeanFactory();
        // 返回上一步剛剛創(chuàng)建的BeanFactory
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }

AbstractRefreshableApplicationContext#refreshBeanFactory()

protected final void refreshBeanFactory() throws BeansException {
        // 如果 ApplicationContext 已經(jīng)加載過 BeanFactory腔呜,銷毀所有的Bean,關(guān)閉BeanFactory
        // 注意點(diǎn):應(yīng)用中BeanFactory是可以有多個的豆挽,這里可不是說全局是否有BeanFactory
        // 而是說當(dāng)前的ApplicationContext有沒有BeanFactory育谬!
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            // 初始化一個 DefaultListableBeanFactory
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            // 用于 BeanFactory 的序列化,一般人應(yīng)該用不到吧...
            beanFactory.setSerializationId(getId());
            // 下面是兩個重點(diǎn)方法
            // 設(shè)置 BeanFactory 的兩個重要屬性
            // 是否允許 Bean 覆蓋帮哈、是否允許循環(huán)引用
            customizeBeanFactory(beanFactory);
            // 加載BeanDefinition到BeanFactory  單獨(dú)拉出來講
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
   }

可以感覺到一個設(shè)計(jì)思路,ApplicationContext 繼承自 BeanFactory锰镀,但是它不應(yīng)該被理解為 BeanFactory 的實(shí)現(xiàn)類娘侍,而是說其內(nèi)部持有一個實(shí)例化的 BeanFactory(DefaultListableBeanFactory)。以后所有的 BeanFactory 相關(guān)的操作其實(shí)是委托給這個實(shí)例來處理的泳炉。

customizeBeanFactory

    protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
        if (this.allowBeanDefinitionOverriding != null) {
            beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
        if (this.allowCircularReferences != null) {
            beanFactory.setAllowCircularReferences(this.allowCircularReferences);
        }
    }

BeanDefinition 的覆蓋問題可能會有開發(fā)者碰到這個坑憾筏,就是在配置文件中定義 bean 時使用了相同的 id 或 name。

默認(rèn)情況下花鹅,allowBeanDefinitionOverriding 屬性為 null(Boolean類型)氧腰,如果在同一配置文件中重復(fù)了,會拋錯,但是如果不是同一配置文件中古拴,會發(fā)生覆蓋箩帚。

  • 循環(huán)引用也很好理解:A 依賴 B,而 B 依賴 A黄痪〗襞粒或 A 依賴 B,B 依賴 C桅打,而 C 依賴 A是嗜。

  • 默認(rèn)情況下,Spring 允許循環(huán)依賴挺尾,當(dāng)然如果你在 A 的構(gòu)造方法中依賴 B鹅搪,在 B 的構(gòu)造方法中依賴 A 是不行的

loadBeanDefinitions(beanFactory) 加載BeanDefinition

    /**
     * Load bean definitions into the given bean factory, typically through
     * delegating to one or more bean definition readers.
     * @param beanFactory the bean factory to load bean definitions into
     * @throws BeansException if parsing of the bean definitions failed
     * @throws IOException if loading of bean definition files failed
     * @see org.springframework.beans.factory.support.PropertiesBeanDefinitionReader
     * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
     */
    protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
            throws BeansException, IOException;

ClassPathXmlApplicationContext 是按照解析XML的加載方式遭铺±鍪粒看javadoc的描述,是通過XmlBeanDefinitionReader來載入Bean Definitions掂僵。

    /**
     * Loads the bean definitions via an XmlBeanDefinitionReader.
     * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
     * @see #initBeanDefinitionReader
     * @see #loadBeanDefinitions
     */
    @Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        // Create a new XmlBeanDefinitionReader for the given BeanFactory.
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
        // Configure the bean definition reader with this context's
        // resource loading environment.
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
        // Allow a subclass to provide custom initialization of the reader,
        // 初始化Reader 不重要航厚,看下這個方法的javadoc就很好理解了
        initBeanDefinitionReader(beanDefinitionReader);
        // 真正重要的步驟!锰蓬!
        // 用Reader去加載XML配置
        loadBeanDefinitions(beanDefinitionReader);
    }

loadBeanDefinitions(beanDefinitionReader)

    /**
     * Load the bean definitions with the given XmlBeanDefinitionReader.
     * 看這句注釋:this method is just supposed to load and/or register bean definitions.
     */
    protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
        Resource[] configResources = getConfigResources();
        if (configResources != null) {
            reader.loadBeanDefinitions(configResources);
        }
        String[] configLocations = getConfigLocations();
        if (configLocations != null) {
            // 這個分支幔睬,通過路徑名去獲取Resource,會和上面的方法殊途同歸
            reader.loadBeanDefinitions(configLocations);
        }
    }

AbstractBeanDefinitionReader#loadBeanDefinitions(Resource... resources)

    @Override
    public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
        Assert.notNull(resources, "Resource array must not be null");
        int counter = 0;
        for (Resource resource : resources) {
            // 遍歷解析XML文件芹扭,加載 BeanDefinition
            counter += loadBeanDefinitions(resource);
        }
        return counter;
    }

接下去的源碼不細(xì)講麻顶,這里載入分為兩大步,

  1. 就是通過調(diào)用XML的解析器獲取到 document 對象舱卡,完成通用XML解析辅肾;

  2. 就是按照Spring的Bean規(guī)則進(jìn)行解析

    • Spring的Bean規(guī)則進(jìn)行解析這個過程是BeanDefinitionDocumentReader來實(shí)現(xiàn)的轮锥,里面包含了各種Spring Bean定義規(guī)則的處理矫钓。

    • 這里我覺得核心知識點(diǎn)就是Spring Bean規(guī)則的解析,簡單點(diǎn)來說舍杜,里面包含了我們在XML配置的那些信息新娜,怎么解析成容器中 BeanDefinition的規(guī)則和步驟。這部分由于和主要流程關(guān)系不大既绩。

    • 在這因?yàn)镾pring 的 Bean配置方式有很多概龄,解析配置信息到BeanDefinition的實(shí)現(xiàn)方式也有很多,XML又是現(xiàn)在少用的方式饲握,所以關(guān)于XML中的Spring Bean規(guī)則的解析的詳細(xì)源碼就先略過了私杜。

我們來看下prepareBeanFactory(beanFactory)這個方法

設(shè)置 BeanFactory的類加載器蚕键,添加幾個 BeanPostProcessor,手動注冊幾個特殊的 bean

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    //設(shè)置類加載器衰粹,為當(dāng)前應(yīng)用的application的類加載器
    beanFactory.setBeanClassLoader(getClassLoader());
    //為bean工廠設(shè)置一個標(biāo)準(zhǔn)的SPEL表達(dá)式解析器
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    //為bean工廠設(shè)置一個資源編輯器锣光,為了后面bean初始化時,給bean對象賦值
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
    //忽略以下接口的bean寄猩,這些bean都有set方法嫉晶,不會對這些bean進(jìn)行屬性賦值
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
    //注冊了工廠實(shí)例,如果我們在程序中注入BeanFactory田篇,就是從這里注冊的獲取到的
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);
    //注冊事件監(jiān)聽器的bean后置處理接口
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
    //處理AOP的后置處理器
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
    //注冊bean工廠的環(huán)境屬性
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

接下來分析postProcessBeanFactory(beanFactory);

  • 這里需要知道BeanFactoryPostProcessor 這個知識點(diǎn)替废,Bean 如果實(shí)現(xiàn)了此接口, 那么在容器初始化以后泊柬,Spring 會負(fù)責(zé)調(diào)用里面的 postProcessBeanFactory 方法椎镣。

    • 提供給子類的擴(kuò)展點(diǎn),到這里的時候兽赁,所有的Bean都加載状答、注冊完成了,但是都還沒有初始化刀崖。

    • 具體的子類可以在這步的時候添加一些特殊的 BeanFactoryPostProcessor 的實(shí)現(xiàn)類或做點(diǎn)什么事惊科。

    • 該方法沒有做實(shí)際的事情,主要是把ServletContextAwareProcessor后置處理器亮钦,給注冊進(jìn)去馆截。

    • 實(shí)現(xiàn)ServletContextAware接口獲取上下文容器,就是從這里注入的蜂莉。


protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    if (this.servletContext != null) {
        beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
        beanFactory.ignoreDependencyInterface(ServletContextAware.class);
    }
    WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
    WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
}

接下來分析invokeBeanFactoryPostProcessors(beanFactory);

調(diào)用BeanFactoryPostProcessor實(shí)現(xiàn)類 postProcessBeanFactory(factory) 方法

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    //獲取FactoryPostProcessors蜡娶,Spring內(nèi)置的和自己設(shè)置的,然后供接下來的調(diào)用
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}

public static void invokeBeanFactoryPostProcessors(
        ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    //放入已經(jīng)被處理過的bean
    Set<String> processedBeans = new HashSet<>();
    //當(dāng)前bean工廠是否實(shí)現(xiàn)了BeanDefinitionRegistry映穗,如果有的話窖张,則可以注冊bean定義
    if (beanFactory instanceof BeanDefinitionRegistry) {
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
        //循環(huán)我們傳入的bean工廠后置處理器,并加入到處理器集合中
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                BeanDefinitionRegistryPostProcessor registryProcessor =
                        (BeanDefinitionRegistryPostProcessor) postProcessor;
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                registryProcessors.add(registryProcessor);
            }
            else {
                regularPostProcessors.add(postProcessor);
            }
        }
        //保存當(dāng)前實(shí)例化的BeanDefinitionRegistryPostProcessor
        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
        //從bean工廠中獲取到繼承了BeanDefinitionRegistryPostProcessor的bean
        String[] postProcessorNames =
              beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            //實(shí)例化優(yōu)先級最高的BeanDefinitionRegistryPostProcessor
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                //實(shí)例化出BeanDefinitionRegistryPostProcessor的類蚁滋,我們正常初始化這里只有ConfigurationClassPostProcessor
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        //對實(shí)例化出來的BeanDefinitionRegistryPostProcessor進(jìn)行排序
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        //把實(shí)例化出來的BeanDefinitionRegistryPostProcessor添加進(jìn)總的集合中供后面調(diào)用
        registryProcessors.addAll(currentRegistryProcessors);
        //調(diào)用剛實(shí)例化出來的bean宿接,注冊bean定義
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        //清空調(diào)用后的BeanDefinitionRegistryPostProcessor
        currentRegistryProcessors.clear();

        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            //實(shí)例化實(shí)現(xiàn)了Ordered接口的BeanDefinitionRegistryPostProcessor
            if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        currentRegistryProcessors.clear();
        //調(diào)用沒有實(shí)現(xiàn)任何優(yōu)先級接口的BeanDefinitionRegistryPostProcessor
        boolean reiterate = true;
        while (reiterate) {
            reiterate = false;
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (!processedBeans.contains(ppName)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                    reiterate = true;
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();
        }
        //調(diào)用 BeanDefinitionRegistryPostProcessor.postProcessBeanFactory方法
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        //調(diào)用自己實(shí)現(xiàn)的BeanDefinitionRegistryPostProcessor.postProcessBeanFactory方法
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    }
    else {
        //沒有實(shí)現(xiàn)BeanDefinitionRegistry接口的bean工廠,直接調(diào)用invokeBeanFactoryPostProcessors
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }
    //調(diào)用所有的BeanDefinitionRegistryPostProcessor完畢
    //獲取容器中所有的 BeanFactoryPostProcessor
    String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
    //執(zhí)行所有BeanFactoryPostProcessor.postProcessBeanFactory方法辕录,按照order接口排序
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
        if (processedBeans.contains(ppName)) {
        }
        else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    for (String postProcessorName : orderedPostProcessorNames) {
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
    //執(zhí)行完成所有BeanFactoryPostProcessor.postProcessBeanFactory方法澄阳,清除所有緩存信息
    beanFactory.clearMetadataCache();
}
//我們接下來主要是看ConfigurationClassPostProcessor調(diào)用postProcessBeanDefinitionRegistry方法
private static void invokeBeanDefinitionRegistryPostProcessors(
        Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
    for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
        postProcessor.postProcessBeanDefinitionRegistry(registry);
    }
}

接下來主要針對于,ConfigurationClassParser類進(jìn)行解析操作處理

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    int registryId = System.identityHashCode(registry);
    if (this.registriesPostProcessed.contains(registryId)) {
        throw new IllegalStateException(
                "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
    }
    if (this.factoriesPostProcessed.contains(registryId)) {
        throw new IllegalStateException(
                "postProcessBeanFactory already called on this post-processor against " + registry);
    }
    this.registriesPostProcessed.add(registryId);
    processConfigBeanDefinitions(registry);
}

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
    String[] candidateNames = registry.getBeanDefinitionNames();
    //循環(huán)最開始初始化的所有bean定義
    for (String beanName : candidateNames) {
        BeanDefinition beanDef = registry.getBeanDefinition(beanName);
        //對配置類(帶有@Configuration標(biāo)簽)進(jìn)行標(biāo)記踏拜,后續(xù)實(shí)例化時有用
        if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
            if (logger.isDebugEnable()) {
                logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
            }
        }
        //進(jìn)行標(biāo)記,添加到配置類低剔,候選集合中
        else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
            configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
        }
    }
    if (configCandidates.isEmpty()) {
        return;
    }
    //對所有配置類進(jìn)行排序
    configCandidates.sort((bd1, bd2) -> {
        int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
        int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
        return Integer.compare(i1, i2);
    });
    // 創(chuàng)建我們通過@ComponentScan導(dǎo)入進(jìn)來的bean name的生成器
    // 創(chuàng)建我們通過@Import導(dǎo)入進(jìn)來的bean的名稱
    SingletonBeanRegistry sbr = null;
    if (registry instanceof SingletonBeanRegistry) {
        sbr = (SingletonBeanRegistry) registry;
        if (!this.localBeanNameGeneratorSet) {
            BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
                    AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
            if (generator != null) {
                this.componentScanBeanNameGenerator = generator;
                this.importBeanNameGenerator = generator;
            }
        }
    }
    if (this.environment == null) {
        this.environment = new StandardEnvironment();
    }
    //創(chuàng)建一個類解析器
    ConfigurationClassParser parser = new ConfigurationClassParser(
            this.metadataReaderFactory, this.problemReporter, this.environment,
            this.resourceLoader, this.componentScanBeanNameGenerator, registry);

    Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
    Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
    do {
        /**解析配置類速梗,包括@Component肮塞、@ComponentScans等需要掃描的類,都會被解析出來放入bean定義容器
         *@Configuration配置類為full配置類姻锁,其他的為lite配置類
         **/
        parser.parse(candidates);
        parser.validate();
        //獲取到解析出來的配置類
        Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
        configClasses.removeAll(alreadyParsed);
        if (this.reader == null) {
            this.reader = new ConfigurationClassBeanDefinitionReader(
                    registry, this.sourceExtractor, this.resourceLoader, this.environment,
                    this.importBeanNameGenerator, parser.getImportRegistry());
        }
        //把所有@Import枕赵、@Bean解析出來的bean定義放入容器
        this.reader.loadBeanDefinitions(configClasses);
        alreadyParsed.addAll(configClasses);
        candidates.clear();
        if (registry.getBeanDefinitionCount() > candidateNames.length) {
            String[] newCandidateNames = registry.getBeanDefinitionNames();
            Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
            Set<String> alreadyParsedClasses = new HashSet<>();
            for (ConfigurationClass configurationClass : alreadyParsed) {
                alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
            }
            for (String candidateName : newCandidateNames) {
                if (!oldCandidateNames.contains(candidateName)) {
                    BeanDefinition bd = registry.getBeanDefinition(candidateName);
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                            !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                        candidates.add(new BeanDefinitionHolder(bd, candidateName));
                    }
                }
            }
            candidateNames = newCandidateNames;
        }
    }
    while (!candidates.isEmpty());
    if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
        sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
    }
    if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
        ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
    }
}
//我們再來看看ConfigurationClassPostProcessor.invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    int factoryId = System.identityHashCode(beanFactory);
    if (this.factoriesPostProcessed.contains(factoryId)) {
        throw new IllegalStateException(
                "postProcessBeanFactory already called on this post-processor against " + beanFactory);
    }
    this.factoriesPostProcessed.add(factoryId);
    if (!this.registriesPostProcessed.contains(factoryId)) {
        processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
    }
    //這里會修改@Configuration配置類的bean定義,到時候?qū)嵗痓ean時位隶,會使用CGLIB創(chuàng)建動態(tài)代理拷窜,@Bean中調(diào)用獲取的bean都是容器中的bean,其他配置類的bean涧黄,獲取的都是new出來的
    enhanceConfigurationClasses(beanFactory);
    beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}

講了bean定義的加載過程篮昧,現(xiàn)在我們來講一下bean的實(shí)例化過程,bean的實(shí)例化笋妥,主要是finishBeanFactoryInitialization(beanFactory);這個方法

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    //bean工廠創(chuàng)建轉(zhuǎn)化器
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
            beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
        beanFactory.setConversionService(
                beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
    }
    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    }
    //實(shí)例化AOP相關(guān)的組件
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
        //調(diào)用工廠實(shí)例化方法懊昨,這個方法我們后面來分析
        getBean(weaverAwareName);
    }
    beanFactory.setTempClassLoader(null);
    //凍結(jié)所有bean定義,在實(shí)例化時春宣,不允許再修改bean定義
    beanFactory.freezeConfiguration();
    //實(shí)例化所有bean
    beanFactory.preInstantiateSingletons();
}

Spring IOC容器bean的實(shí)例化酵颁,到這基本就完成了,這次所有源代碼的分析把重要的地方月帝,大致流程都講了一遍躏惋,但是有很多細(xì)節(jié)沒有講到,整體屬于框架總體深入流程原理介紹嚷辅。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末簿姨,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子潦蝇,更是在濱河造成了極大的恐慌款熬,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件攘乒,死亡現(xiàn)場離奇詭異贤牛,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)则酝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門殉簸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人沽讹,你說我怎么就攤上這事般卑。” “怎么了爽雄?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵蝠检,是天一觀的道長。 經(jīng)常有香客問我挚瘟,道長叹谁,這世上最難降的妖魔是什么饲梭? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮焰檩,結(jié)果婚禮上憔涉,老公的妹妹穿的比我還像新娘。我一直安慰自己析苫,他們只是感情好兜叨,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著衩侥,像睡著了一般国旷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上顿乒,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天议街,我揣著相機(jī)與錄音,去河邊找鬼璧榄。 笑死特漩,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的骨杂。 我是一名探鬼主播涂身,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼搓蚪!你這毒婦竟也來了蛤售?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤妒潭,失蹤者是張志新(化名)和其女友劉穎悴能,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雳灾,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡漠酿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了谎亩。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片炒嘲。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖匈庭,靈堂內(nèi)的尸體忽然破棺而出夫凸,到底是詐尸還是另有隱情,我是刑警寧澤阱持,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布夭拌,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏啼止。R本人自食惡果不足惜道逗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望献烦。 院中可真熱鬧,春花似錦卖词、人聲如沸巩那。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽即横。三九已至,卻和暖如春裆赵,著一層夾襖步出監(jiān)牢的瞬間东囚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工战授, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留页藻,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓植兰,卻偏偏與公主長得像份帐,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子楣导,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容