Spring IOC 容器預(yù)啟動流程源碼探析

Spring IOC 容器預(yù)啟動流程源碼探析

在應(yīng)用程序中,一般是通過創(chuàng)建ClassPathXmlApplicationContextAnnotationConfigApplicationContext這兩個最底層子類來啟動Spring IOC容器:

  • ClassPathXmlApplicationContext: xml文件配置版
  • AnnotationConfigApplicationContext: 注解版

由于當(dāng)下越來越流行基于Java注解的配置來創(chuàng)建我們的Bean,所以本文主要以注解版進(jìn)行探析。

AnnotationConfigApplicationContext的類關(guān)系結(jié)構(gòu)

我們先來看看我們探討的起點(diǎn)

public class Main {

    public static void main(String[] args) {
        new AnnotationConfigApplicationContext(Config.class);
    }
    @Configuration
    public static class Config{

    }
}

demo簡簡單單,那么,這里發(fā)生了什么?或許,我們可以先看看AnnotationConfigApplicationContext的類關(guān)系結(jié)構(gòu):

在這里插入圖片描述

我們可以看到AnnotationConfigApplicationContext最上面有兩個頂級接口:

  • BeanFactory: Spring的核心接口,純粹的bean容器,主要定義了與Bean的相關(guān)方法
  • ResourceLoader:資源加載器,定義了getResource方法

繼承自三個父類:

  • DefaultResourceLoader: 默認(rèn)的資源加載器,實(shí)現(xiàn)了三種加載資源的方式

    1. 通過path加載資源

    2. 通過classpath加載資源

    3. 通過URL加載資源

  • AbstractApplicationContext: 實(shí)現(xiàn)了ApplicationContext接口的抽象類,主要功能

    1. 實(shí)現(xiàn)了啟動IOC容器的核心方法:refresh()

    2. 發(fā)布事件

    3. 大量getBean相關(guān)的操作, 主要通過抽象方法getBeanFactory基于子類實(shí)現(xiàn)

    4. 大量留于子類擴(kuò)展的空方法

    5. 消息國際化

  • GenericApplicationContext:

    1. 使用組合的方式引進(jìn)了最底層的BeanFactory實(shí)現(xiàn)類:DefaultListableBeanFactory

    2. 定義了registerBean的相關(guān)操作,其實(shí)是通過DefaultListableBeanFactory實(shí)現(xiàn)的

不難發(fā)現(xiàn),ApplicationContext名副其實(shí),確實(shí)就是一個應(yīng)用上下文,對于bean的相關(guān)操作,容器的管理,依舊是由我們的BeanFactory進(jìn)行實(shí)現(xiàn)。

準(zhǔn)備啟動

1. 創(chuàng)建我們的實(shí)例:AnnotationConfigApplicationContext

new AnnotationConfigApplicationContext(Config.class);

2.進(jìn)入到AnnotationConfigApplicationContext構(gòu)造方法

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    this();
    register(annotatedClasses);
    refresh();
}

3. 調(diào)用我們的空構(gòu)造方法,這里要先實(shí)例化我們的父類

3.1 實(shí)例化DefaultResourceLoader

public DefaultResourceLoader() {
    this.classLoader = ClassUtils.getDefaultClassLoader();
}

ClassUtils.getDefaultClassLoader()主要有兩步操作

//獲取線程上下文的類加載器
ClassLoader cl = = Thread.currentThread().getContextClassLoader();
if(cl == null) //為空則獲取系統(tǒng)的類加載器 即為應(yīng)用類加載器
    cl = ClassLoader.getSystemClassLoader();

這里我們非Tomcat環(huán)境,所以返回的是AppClassLoader

3.2 實(shí)例化AbstractApplicationContext

//為BeanFactoryPostProcessor賦初始值
List<BeanFactoryPostProcessor> BeanFactoryPostProcessor = new ArrayList<>();
public AbstractApplicationContext() {
    //引入一個資源解析器
    this.resourcePatternResolver = getResourcePatternResolver();
}
protected ResourcePatternResolver getResourcePatternResolver() {
    return new PathMatchingResourcePatternResolver(this);
}

3.3 實(shí)例化GenericApplicationContext

public GenericApplicationContext() {
    //引入BeanFactory實(shí)現(xiàn)
    this.beanFactory = new DefaultListableBeanFactory();
}

3.4 實(shí)例化自己

public AnnotationConfigApplicationContext() {
    //初始化基于注解的bean定義掃描器
    this.reader = new AnnotatedBeanDefinitionReader(this);
    //初始化基于classpath的bean定義掃描器
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}
3.4.1 AnnotatedBeanDefinitionReader初始化過程
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
    this(registry, getOrCreateEnvironment(registry));
}
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
    //registry就是我們AnnotationConfigApplicationContext
    this.registry = registry;
    //引入條件表達(dá)式計算器 處理@Conditional注解
    this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
    //注冊所有與注解相關(guān)的后置處理器
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)

public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
    registerAnnotationConfigProcessors(registry, null);
}

registerAnnotationConfigProcessors(registry, null)中主要做了以下幾件事情:

  • DefaultListableBeanFactory賦值了兩個引用

    //依賴排序器,用于處理添加了Priority、Order注解以及實(shí)現(xiàn)了Ordered接口的bean
    beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
    //@Autowire候選解析器
    beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
    
  • 往容器中注冊了6個后置處理器的bean定義

    注冊配置類的后置處理器

    RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
    def.setSource(source);
    registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME);
    

    注冊處理@Autowired注解的后置處理器

    RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
    def.setSource(source);
    registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME);
    

    注冊處理@Required注解的后置處理器(5.1版本開始已被廢棄)

    RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
    def.setSource(source);
    registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME);
    

    注冊處理JSR-250規(guī)范注解的后置處理器,@Resource,@PostConstruct,@PreDestroy

    RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
    def.setSource(source);
    registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME);
    

    注冊處理@EventListener注解的后置處理器

    RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
    def.setSource(source);
    registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME);
    

    注冊事件監(jiān)聽工廠,給上面的EventListenerMethodProcessors使用

    RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
    def.setSource(source);
    registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME);
    
3.4.2 ClassPathBeanDefinitionScanner初始化過程

經(jīng)歷了一系列的構(gòu)造器傳遞

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
    this(registry, true);
}

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
    this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
}

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
                                      Environment environment) {
    this(registry, useDefaultFilters, environment,
         (registry instanceof ResourceLoader ? (ResourceLoader) registry : null));
}

最終實(shí)現(xiàn)的構(gòu)造器方法

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
                                      Environment environment, @Nullable ResourceLoader resourceLoader) {

    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    this.registry = registry;
    //默認(rèn)為true
    if (useDefaultFilters) {
        //注冊默認(rèn)的過濾器
        registerDefaultFilters();
    }
    //設(shè)置環(huán)境
    setEnvironment(environment);
    //設(shè)置資源加載器
    setResourceLoader(resourceLoader);
}

registerDefaultFilters方法

protected void registerDefaultFilters() {
    //加入掃描@Component注解的過濾器,這樣就能掃到@Controller,@Service...
    this.includeFilters.add(new AnnotationTypeFilter(Component.class));
    ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
    try {
        //JSR-250規(guī)范的注解
        this.includeFilters.add(new AnnotationTypeFilter(
            ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
    }
    catch (ClassNotFoundException ex) {
    }
    try {
        //JSR-330規(guī)范的注解
        this.includeFilters.add(new AnnotationTypeFilter(
            ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
    }
    catch (ClassNotFoundException ex) {
    }
}

4. 構(gòu)造方法執(zhí)行完畢,執(zhí)行register(annotatedClasses)方法,將配置類的bean定義注冊到容器中

public void register(Class<?>... annotatedClasses) {
    Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
    //這里就使用了剛剛初始化的AnnotatedBeanDefinitionReader掃碼器
    //annotatedClasses即為在入口處傳進(jìn)的自定義配置類Config.class
    this.reader.register(annotatedClasses);
}
public void register(Class<?>... annotatedClasses) {
    for (Class<?> annotatedClass : annotatedClasses) {
        //這里我們只傳了一個,只有一次循環(huán)
        registerBean(annotatedClass);
    }
}
public void registerBean(Class<?> annotatedClass) {
    //spring的特點(diǎn),真正實(shí)現(xiàn)的都是do開頭的方法
    doRegisterBean(annotatedClass, null, null, null);
}
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
                        @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
    //將class封裝到bean定義中
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
    //由于配置類并未使用@Conditional注解,直接返回false
    if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
        return;
    }

    abd.setInstanceSupplier(instanceSupplier);
    //解析bean定義的作用域
    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
    abd.setScope(scopeMetadata.getScopeName());
    String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
    //處理普通的bean定義注解,@Lazy @Primary @DependsOn @Role @Description
    AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
    if (qualifiers != null) {
        for (Class<? extends Annotation> qualifier : qualifiers) {
            if (Primary.class == qualifier) {
                abd.setPrimary(true);
            }
            else if (Lazy.class == qualifier) {
                abd.setLazyInit(true);
            }
            else {
                abd.addQualifier(new AutowireCandidateQualifier(qualifier));
            }
        }
    }
    for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
        customizer.customize(abd);
    }

    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    //根據(jù)scopeMetadata中的proxy-mode屬性判斷是否需要進(jìn)行代理封裝,默認(rèn)否
    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    //將bean定義注冊到容器中
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
} 

前期準(zhǔn)備工作已基本完畢,可以開始調(diào)用refresh方法啟動IOC容器了。

準(zhǔn)備花個30天時間,系統(tǒng)的來整理一下我對spring源碼的認(rèn)識:

Spring 源碼系列
  1. Spring源碼分析之 IOC 容器預(yù)啟動流程(已完結(jié))
  2. Spring源碼分析之BeanFactory體系結(jié)構(gòu)(已完結(jié))
  3. Spring源碼分析之BeanFactoryPostProcessor調(diào)用過程(已完結(jié))
  4. Spring源碼分析之Bean的創(chuàng)建過程
  5. Spring源碼分析之什么是循環(huán)依賴及解決方案
  6. Spring源碼分析之AOP從解析到調(diào)用
  7. Spring源碼分析之事務(wù)管理(上),事物管理是spring作為容器的一個特點(diǎn),總結(jié)一下他的基本實(shí)現(xiàn)與原理吧
  8. Spring源碼分析之事務(wù)管理(下) ,關(guān)于他的底層事物隔離與事物傳播原理,重點(diǎn)分析一下
Spring Mvc 源碼系列
  1. SpringMvc體系結(jié)構(gòu)
  2. SpringMvc源碼分析之Handler解析過程
  3. SpringMvc源碼分析之請求鏈過程
Mybatis 源碼系列

暫定


追更,可關(guān)注我的公眾號:奇客時間,分享純粹為了樂趣,也有一種成就感吧,筆者這篇文章先就到這

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容