• Spring Boot启动流程源码解析


    定义:

    BeanFactoryPostProcessor:是一个接口,它允许自定义修改应用程序上下文的beanDefiinition

    BeanDefinitionRegistryPostProcessor:是一个接口,继承接口BeanFactoryPostProcessor,该接口新增postProcessBeanDefinitionRegistry方法,方法参数是BeanDefinitionRegistry对象,BeanDefinitionRegistry对象是beanDefiinition的保存中心

    BeanPostProcessor:在bean实例化的时候,进行切面处理,在实例化的前执行postProcessBeforeInitialization,在实例化后执行postProcessAfterInitialization 

     

    一、SpringApllication实例化,进行初始化操作:

    this.resourceLoader = resourceLoader;   // 资源加载器,resourceLoader = null
    Assert.notNull(primarySources, "PrimarySources must not be null");  //
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); //赋值启动类
    this.webApplicationType = WebApplicationType.deduceFromClasspath(); //根据classpath存在的类推断web所属应用类型:servelt,Reactive,后面根据不同的类型初始化对应的环境
    this.bootstrapRegistryInitializers = getBootstrapRegistryInitializersFromSpringFactories(); //获取启动加载器
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); //设置初始化器
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); //设置监听器
    this.mainApplicationClass = deduceMainApplicationClass(); //根据运行调用栈track,根据main方法找到入口启动类
    getBootstrapRegistryInitializersFromSpringFactories() :获取启动加载器

    它调用getSpringFactoriesInstances(Bootstrapper.class),在多个应用的META-INF/spring.factories文件下获取,key=Bootstrapper的启动类加载器的包路径,并通过class.forName反射,然后把实例放到集合进行Order排序,设置优先级,返回集合。

    但是此处,由于META-INF/spring.factories文件没有key=Bootstrapper的信息,故返回了一个空集合。

     

    setInitializers(getSpringFactoriesInstances(ApplicationContextInitializer.class))):设置初始化器

    getSpringFactoriesInstances(ApplicationContextInitializer.class))的作用:在多个应用的META-INF/spring.factories文件下获取,key=ApplicationContextInitializer初始化器的包路径,并通过class.forName反射,然后把实例放到集合进行Order排序,设置优先级,返回集合,并通过setInitializers对本对象属性initializers(初始化器)进行赋值。初始化器,在spring容器刷新之前,进行接口回调initialize方法

    返回的初始化器如下:

    0 = "org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer"
        作用:用作报告常见错误配置的警告(通过分析源码实际情况是如果系统配置包扫描(@ComponentScan)到了org或者org.springframework包就会发出警告并停止系统启动)
        
    1 = "org.springframework.boot.context.ContextIdApplicationContextInitializer"
        作用:用于获取、设置spring上下文ID
        
    2 = "org.springframework.boot.context.config.DelegatingApplicationContextInitializer"
        作用:使用环境属性 context.initializer.classes,指定的初始化器(initializers)进行初始化工作,如果没有指定则什么都不做。 通过它使得我们可以把自定义实现类配置在 application.properties 里成为了可能。
        
    3 = "org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer"
        作用:为server设置local.rsocket.server.port通讯监听端口
        
    4 = "org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer"
        作用:将内置servlet容器实际使用的监听端口写入到Environment环境属性中。这样属性local.server.port就可以直接通过@Value注入到测试中,或者通过环境属性Environment获取。
        
    5 = "org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer"
        作用:创建一个SpringBoot和ConfigurationClassPostProcessor共用的CachingMetadataReaderFactory对象。实现类为:ConcurrentReferenceCachingMetadataReaderFactory
        
    6 = "org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener"
        作用:将ConditionEvaluationReport报告写入日志。
     

     

    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)) :设置监听器

    getSpringFactoriesInstances(ApplicationListener.class)的作用:在多个应用的META-INF/spring.factories文件下获取,key=ApplicationListener初始化器的包路径,并通过class.forName反射,然后把实例放到集合进行Order排序,设置优先级,返回集合,并通过setListeners对本对象属性listeners(监听器)进行赋值。

    返回的监听器如下:

     0 = "org.springframework.boot.ClearCachesApplicationListener"
         作用:上下文加载完成后,清理缓存,比如,从META-INF/spring.factories获取的信息后,会放到cache,下次直接从cache拿。
         
     1 = "org.springframework.boot.builder.ParentContextCloserApplicationListener"
         作用:监听当双亲应用的上下文关闭,如果双亲应用关闭了,自身也要关闭。从这个类中拿到上下文去刷新监听双亲关闭事件。
         
     2 = "org.springframework.boot.context.FileEncodingApplicationListener"
         作用:文件编码应用监听器。该监听器实质作用是在收到应用环境准备就绪事件时,对配置中关于文件编码的配置作一个校验,判断配置中的文件编码是否和JVM系统的file.encoding一致。无配置或JVM系统的file.encoding无效的情况下,都不会报异常,但是,当JVM中的file.encoding有效,且在配置中包含了spring.mandatory-file-encoding,而二者又不一致时,就会报IllegalStateException异常。
         
     3 = "org.springframework.boot.context.config.AnsiOutputApplicationListener"
         作用:当收到应用环境准备就绪事件时,对Ansi输出的相关状态进行设置,并绑定到应用环境中
         
     4 = "org.springframework.boot.context.config.DelegatingApplicationListener"
         作用:而是在应用环境准备就绪事件发生时,通过环境中的配置的context.listener.classes,指定自定义的监听器,然后创建一个简单事件广播器实例,放到类属性上,同时,把自定义的监听器,绑定到该广播器上。就可以使得我们自定义的监听器发挥作用
         
     5 = "org.springframework.boot.context.logging.LoggingApplicationListener"
         作用:日志配置监听器,如果没配置日志信息,则使用系统默认的配置。
         
     6 = "org.springframework.boot.env.EnvironmentPostProcessorApplicationListener"
         作用:监听环境准备好后,如果配置信息spring.factories指定了“环境后置处理程序”,则运行该后置处理程序。一般用于自定义环境变量或者编写第三方扩展点
         
     7 = "org.springframework.boot.autoconfigure.BackgroundPreinitializer"
         作用:对于一些耗时的任务,使用一个后台线程尽早触发它们开始执行初始化, 这也可以叫做预初始化。
         设置系统属性spring.backgroundpreinitializer.ignore为true可禁用该机制。 禁用时,相应的初始化任务会发生在前台线程。
     

     

    二、SpringApplication的run方法

    StopWatch stopWatch = new StopWatch();
    stopWatch.start(); //用于计时
    //【1】创建临时上下文,临时存放一些上下文数据,使用完后会colse.
    DefaultBootstrapContext bootstrapContext = createBootstrapContext();
    //Spring的上下文
    ConfigurableApplicationContext context = null;
    ​
    //【2】配置系统属性java.awt.headless,如果系统缺少硬件,就让系统模拟对应硬件数据以供使用
    configureHeadlessProperty();
    ​
    //【3】获取应用运行的监听器
    SpringApplicationRunListeners listeners = getRunListeners(args);
    //启动监听器
    listeners.starting(bootstrapContext, this.mainApplicationClass);
    ​
    try {
        //封装形参args
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        
        //【4】准备容器环境,初始化environment,即应用上下文环境
        ConfigurableEnvironment environment 
            = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
        //根据用户自定义spring.beaninfo.ignore,为容器设置需要忽略加载的bean
        configureIgnoreBeanInfo(environment);
        
        //【5】打印spring的logo
        Banner printedBanner = printBanner(environment);
        
        //【6】创建上下文和容器
        context = createApplicationContext();
        //为上下文设置应用启动时候的记录器,如:启动报错的报告
        context.setApplicationStartup(this.applicationStartup);
        
        //【7】刷新上下文的准备阶段
        prepareContext(bootstrapContext, context, environment,
                       listeners, applicationArguments, printedBanner);
        //【8】刷新上下文
        refreshContext(context);
        
        //【9】刷新上下文后操作,空方法
        afterRefresh(context, applicationArguments);
        //停止计时
        stopWatch.stop();
        //打印日志
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass)
                .logStarted(getApplicationLog(), stopWatch);
        }
        //【10】发布“容器加载完成”事件给监听器
        listeners.started(context);
        //【11】调用ApplicationRunner和CommandLineRunner的run方法,实现spring容器启动后需要做的一些东西,比如加载一些业务数据等
        //默认是没有Runner要执行的
        callRunners(context, applicationArguments);
        //发布"应用running"事件
        listeners.running(context);
     

     

    【1】创建临时上下文

    【2】配置系统硬件属性

    【3】获取监听器并启动:getRunListeners(args)

    在META-INF/spring.factories文件下获取key=SpringApplicationRunListener的类路径获得org.springframework.boot.context.event.EventPublishingRunListener

    并通过class.forName反射实例化返回instances,然后通过new SpringApplicationRunListeners( log, instances, applicationStartup),把EventPublishingRunListener封装到SpringApplicationRunListeners的List集合里。

    SpringApplicationRunListener负责在SpringBoot启动的不同阶段,使用内部ApplicationEventMulticaster来广播不同的SpringApplicationEven事件,传递给前面的ApplicatioinListener监听器实现类。比如,“刷新上下文准备阶段” 完成了,就向各个SpringApplicationListener监听器发布“刷新上下文准备阶段” 事件,让各个监听器此时执行对应的逻辑。

     

    【4】准备容器环境:prepareEnvironment

    上下文环境本质上就是环境信息的集合:系统变量、环境变量、JDK环境信息、命令行参数,默认变量,servlet相关配置变量,随机值、JNDI属性值,以及配置文件(比如application.properties)等。

    这些环境变量是有优先级的。对这些信息加载进来,封装到environment对象中。

    发布事件

    具体prepareEnvironment方法:

    //创建相应的应用环境
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    //根据用户配置,配置environment应用环境
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    ConfigurationPropertySources.attach(environment);
    //发布"上下文环境已准备好"事件,其中一个重要的监听器ConfigFileApplicationListener就是加载项目配置文件的
    listeners.environmentPrepared(bootstrapContext, environment);
    //把PropertySources中默认的属性“defaultProperties”,移动到PropertySources的末尾。
    DefaultPropertiesPropertySource.moveToEnd(environment);
    ​
    Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
            "Environment prefix cannot be set via properties.");
    ​
    //将获取到的environment中的spring.main配置绑定到SpringApplication的source中
    bindToSpringApplication(environment);
    //是否为自定义环境
    if (!this.isCustomEnvironment) {
        //把ConfigurableEnvironment根据应用类型转换成对应对应的ApplicationEnviroment
        environment = convertEnvironment(environment);
    }
    // 解除附加的特定的环境配置(避免冲突)
    ConfigurationPropertySources.attach(environment);
    return environment;
     

    创建相应的应用环境:getOrCreateEnvironment

    根据webApplicationType实例化不同的环境类:

    SERVLET -> new ApplicationServletEnvironment()

    REACTIVE -> new ApplicationReactiveWebEnvironment()

    other -> new ApplicationEnvironment()

     

    配置environment应用环境:configureEnvironment

    if (this.addConversionService) {
        environment.setConversionService(new ApplicationConversionService());
    }
    //将main函数的args封装成SimpleCommandLinePropertySource加入环境中 
    configurePropertySources(environment, args);
    //激活相应配置文件,比如:设置spring-profiles.active=prod,封装成SimpleCommandLinePropertySource
    //在此激活application-prod.properties这个配置文件
    configureProfiles(environment, args);
     

     

    【5】打印spring的logo

     

    【6】创建上下文和容器:createApplicationContext()

    根据webApplicationType实例化不同的上下文ConfigurableApplicationContext实现类:

    SERVLET -> new AnnotationConfigServletWebServerApplicationContext()

    REACTIVE -> new AnnotationConfigReactiveWebServerApplicationContext()

    other ->new AnnotationConfigApplicationContext()

    于此同时,因为这几个实现类,继承了GenericApplicationContext,而GenericApplicationContext的构造函数中会创建beanFactory,故子类实例化,父类GenericApplicationContext也会跟着实例化,beanFactory其实际上就是IOC容器,类型为DefaultListableBeanFactory,即上下文中有了一个IOC容器

    public GenericApplicationContext(DefaultListableBeanFactory beanFactory) {
        Assert.notNull(beanFactory, "BeanFactory must not be null");
        this.beanFactory = beanFactory;
    }

     

    【7】刷新上下文准备阶段prepareContext

    1. 在装载好了各种环境配置后,去刷新上下文里的配置;

    2. 并创建一些bean对象,其中包含启动类的bean对象创建。

    //设置上下文环境
    context.setEnvironment(environment);
    //执行容器后置处理:其实就是为ioc的转化器ApplicationConversionService设值
    postProcessApplicationContext(context);
    //执行初始化器的initialize方法
    applyInitializers(context);
    //listeners是SpringApplicationRunListeners,向各个监听器发送"容器已经准备好"的事件,
    listeners.contextPrepared(context);
    ​
    //发布“临时上下文关闭事件”,默认没有监听器监听此事件。
    bootstrapContext.close(context);
    //打印日志信息
    if (this.logStartupInfo) {
        logStartupInfo(context.getParent() == null);
        logStartupProfileInfo(context);
    }
    ​
    // Add boot specific singleton beans
    //向IOC容器中添加args封装成ApplicationArguments的单例
    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
    ​
    //IOC容器添加打印springBootBanner单例
    if (printedBanner != null) {
        beanFactory.registerSingleton("springBootBanner", printedBanner);
    }
    //设置BeanDefinition是否能被重载(修改),默认设置为false
    if (beanFactory instanceof DefaultListableBeanFactory) {
        ((DefaultListableBeanFactory) beanFactory)
                .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }
    //是否懒加载,默认为false
    if (this.lazyInitialization) {
        //上下文添加一个处理bean后置处理器
        context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor())
    }
    // Load the sources,实际上获取的只有启动类对象
    Set<Object> sources = getAllSources();
    Assert.notEmpty(sources, "Sources must not be empty");
    ​
    //加载启动类的beanDefinition,并注入容器中
    load(context, sources.toArray(new Object[0]));
    //发布“容器已加载完成”事件
    listeners.contextLoaded(context);
     

    【8】刷新上下文:refreshContext(context)

    刷新之前,会在context上下文添加一个ApplicationContextClosedListener监听,就是为了在shutdown的时候,优雅的关闭应用。

    刷新的核心代码如下:

    //在应用程序启动期间标记步骤,并收集有关执行上下文数据和处理事件
    StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
    ​
    // Prepare this context for refreshing
    //1.就是对一些属性赋值。
    prepareRefresh();
    ​
    // Tell the subclass to refresh the internal bean factory
    //2.就是获取beanFactory,即IOC容器,并刷新容器=为容器设置id
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    ​
    // Prepare the bean factory for use in this context
    //3.容器初始化属性
    prepareBeanFactory(beanFactory);
    ​
    // Allows post-processing of the bean factory in context subclasses.
    //4.设置beanDefinition的后置处理器、beanFactory的一些属性
    postProcessBeanFactory(beanFactory);
    ​
    //在应用程序启动期间标记步骤,并收集有关执行上下文数据和处理事件
    StartupStep beanPostProcess = .
        this.applicationStartup.start("spring.context.beans.post-process");
    ​
    // Invoke factory processors registered as beans in the context.
    //5.调用容器中的工厂
    invokeBeanFactoryPostProcessors(beanFactory);
    ​
    // Register bean processors that intercept bean creation.
    //6.注册所有bean的后置处理器
    registerBeanPostProcessors(beanFactory);
    beanPostProcess.end(); //空方法
    // Initialize message source for this context.
    // 7.初始化此上下文的消息源,比如国际化
    initMessageSource();
    ​
    // Initialize event multicaster for this context.
    //8.初始化应用事件发布器,并存在IOC容器中
    initApplicationEventMulticaster();
    ​
    // Initialize other special beans in specific context subclasses.
    //9.开始刷新
    onRefresh();
    ​
    // Check for listener beans and register them.
    //10.注册新的监听器
    registerListeners();
    ​
    // Instantiate all remaining (non-lazy-init) singletons.
    //11.实例化剩余非懒加载的单例bean
    finishBeanFactoryInitialization(beanFactory);
    ​
    // Last step: publish corresponding event.
    //12.刷新完成的收尾工作
    finishRefresh();
     

    1、刷新准备阶段:prepareRefresh

    this.startupDate = System.currentTimeMillis(); //记录时间点
    this.closed.set(false); //目前容器非close状态
    this.active.set(true); //目前容器是活跃的
    if (this.logger.isDebugEnabled()) {
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Refreshing " + this);
        } else {
            this.logger.debug("Refreshing " + this.getDisplayName());
        }
    }
    this.initPropertySources(); //默认空方法,让AbstractApplicationContext子类重载
    this.getEnvironment().validateRequiredProperties(); //校验一些必填配置是否可以被解析
    //earlyApplicationListeners、applicationListeners两个监听器相互赋值
    if (this.earlyApplicationListeners == null) {
        this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
    }
    else {
        // Reset local application listeners to pre-refresh state.
        this.applicationListeners.clear();
        this.applicationListeners.addAll(this.earlyApplicationListeners);
    }
    this.earlyApplicationEvents = new LinkedHashSet(); //初始化用于发布事件对象的集合
     

    2、刷新并获取容器:obtainFreshBeanFactory

     

    3、容器初始化属性:prepareBeanFactory(beanFactory)

    beanFactory初始化的值:

    1. 设置类加载器 :setBeanClassLoader

    2.设置Spel表达式的解析器 :setBeanExpressionResolver

    3.添加属性编辑器 :addPropertyEditorRegistrar 添加属性编辑器

    4.添加Bean后置处理器:addBeanPostProcessor

    5.设置忽略指定类的自动装配功能:ignoreDependencyInterface

    6.自动装配是,指定对应接口的注入对象(一个接口可有多个对象):registerResolvableDependency

    7.设置单例:registerSingleton

     

    4、设置beanDefinition的后置处理器、IOC属性:postProcessBeanFactory

    1.设置request、session作用域的注入对象

    2.设置自动装配时接口注入指定对象

     

    5.调用容器中的beanDefinition后置处理器:invokeBeanFactoryPostProcessors

    Set<String> processedBeans = new HashSet<>();
    ​
    if (beanFactory instanceof BeanDefinitionRegistry) {
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
        //注册两个beanDefinition后置处理器:CachingMetadataReaderFactoryPostProcessor、ConfigurationWarningsPostProcessor
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                BeanDefinitionRegistryPostProcessor registryProcessor =
                        (BeanDefinitionRegistryPostProcessor) postProcessor;
                //调用的是:CachingMetadataReaderFactoryPostProcessor类的该方法,作用是注册beanDefinition后置处理器
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                registryProcessors.add(registryProcessor);
            }
            else {
                regularPostProcessors.add(postProcessor);
            }
        }
    ​
        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
    ​
        // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
        //获取对应类型的后置处理器key:internalConfigurationAnnotationProcessor
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                //添加ConfigurationClassPostProcessor后置处理器
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        //设置beanDefinition后置处理器得优先级
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        //收集要注册到容器得后置处理器,经过前面可得3个后置处理器。
        registryProcessors.addAll(currentRegistryProcessors);
        //把ConfigurationClassPostProcessor后置处理器bean注册到容器
        //这是自动装配的重点方法!!!
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
        currentRegistryProcessors.clear();
    ​
        // 执行到这里,重复上一次得操作
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            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, beanFactory.getApplicationStartup());
        currentRegistryProcessors.clear();
        
        //中间都是一些重复类似上面的操作 
        ……
    ​
    // Clear cached merged bean definitions since the post-processors might have
    // modified the original metadata, e.g. replacing placeholders in values...
    //容器清除beanDefinition缓存,因为beanDefinition后置处理器有可能已经修改了beanDefinition的内容,比如占位符
    beanFactory.clearMetadataCache();

     

    ①检索启动类注解入口,自动装配的关键

    invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
    该方法顾名思义,就是调用Bean定义注册后处理器,形参:

    currentRegistryProcessors :BeanDefinition注册后处理器集合,就一个ConfigurationClassPostProcessor类处理器

    registry:BeanDefinition的注册中心,本质是就是IOC容器里有该注册中心Map

    applicationStartup:记录器,用于记录程序执行

    ②调用接口实现方法

    postProcessor.postProcessBeanDefinitionRegistry(registry);
    该处理器为类型ConfigurationClassPostProcessor,是接口BeanDefinitionRegistryPostProcessor的实现类,如实现类:

    CachingMetadataReaderFactoryPostProcessor.postProcessBeanDefinitionRegistry:是把beanDefinition注册到容器中;

    ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry:是处理有注解的beanDefinition,该方法实现逻辑:

    一、在beanDefinition容器中,通过判断是否包含注解@component,拿到启动类

    二、通过ConfigurationClassParser.parser解析

    1:先解析到@SpringBootApplication,把启动类的beanDefinition封装成SourceClass,被用来更直接检测包含哪些注解的一个类

    2:通过递归处理内部类,把有注解的类记录下来

    3:解析标注@PropertySource的类,处理类成员的值

    4:解析标注@ComponentScan的类,检测到启动类,在启动类所在包及子包进行扫描,直接或间接标注@component的类,都会被扫描到,并把对应类的beanDefinition注册到容器中,然后递归调用ConfigurationClassParser.parser进行解析。

    5:解析标注@Import的类,递归解析自身和父注解的@import,解析到@import.value=ImportBeanDefinitionRegistrar 进行记录;解析到@import.value=ImportSelector进行记录,并通过调用selectImports方法把扫描配置文件META-INF/spring.factories,把里面的类扫描,并检测这类是否有注解,如果有,则也需要递归调用ConfigurationClassParser.parser进行解析

    经过这一系列解析,就通过注解拿到了全部需要实例化注入到IOC容器的类

      

    6、注册bean的后置处理器:registerBeanPostProcessors

    注册方式:PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, applicationContent);

     

    7、初始化此上下文的消息源:initMessageSource

    比如:国际化

     

    8、初始化应用事件发布器,并存在IOC中:initApplicationEventMulticaster

     

    9、开始刷新:onRefresh

    1.初始化主题来源ThemeSource

    2.构造TomcatServletWebServer,并初始化server的配置,并注入到IOC容器中

     

    10、注册监听器:registerListeners

     

    11.实例化剩余非懒加载的单例:finishBeanFactoryInitialization

    拿到容器中的beanDefinition集合,结合bean后置处理器进行实例化,并注入到IOC容器中

     

    12.刷新完成的收尾工作:finishRefresh()

    1.设置管理bean生命周期的LifecycleProcessor处理器

    2.用LifecycleProcessor开始webServerGracefulShutdown、webServerStartStop两个Group 的生命周期管理

    3.发布”容器刷新完成“事件

    4.为MBeanServer注册LiveBeansView

     

    【9】刷新上下文后操作:afterRefresh,空方法

    【10】发布“容器加载完成”事件给监听器:listeners.started

    【11】启动Spring的Runner加载容器启动后数据

  • 相关阅读:
    luogu P3327 [SDOI2015]约数个数和
    生成函数
    luogu P4318 完全平方数
    SP5971 LCMSUM
    luogu P2522 [HAOI2011]Problem b
    UOJ #82. 【UR #7】水题生成器
    CF1147F Zigzag Game
    CF1106F Lunar New Year and a Recursive Sequence
    1114: 逆序
    1113: 递归调用的次数统计(函数专题)
  • 原文地址:https://www.cnblogs.com/incognitor/p/16049092.html
Copyright © 2020-2023  润新知