美文网首页spring
SpringApplication

SpringApplication

作者: b6d5ffb96342 | 来源:发表于2022-03-03 11:08 被阅读0次

初始化SpringApplication

springboot程序的启动,就是实例化SpringApplication,然后调用run方法。

public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
    return new SpringApplication(sources).run(args);
}

实例化时执行如下初始化方法

private void initialize(Object[] sources) {
    if (sources != null && sources.length > 0) {
        this.sources.addAll(Arrays.asList(sources));
    }
    //判断是否web环境
    this.webEnvironment = deduceWebEnvironment();
    //加载初始化器
    setInitializers((Collection) getSpringFactoriesInstances(
        ApplicationContextInitializer.class));
    //加载监听器
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    //定位main函数的类
    this.mainApplicationClass = deduceMainApplicationClass();
}

其中getSpringFactoriesInstances方法,负责从spring.factory文件中读取出要加载的类,并且实例化。(细节见源码,不复杂)

private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,
                                                                Class<?>[] parameterTypes, Object... args) {
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    //从spring.factory中读取要加载的类
    Set<String> names = new LinkedHashSet<String>(
        SpringFactoriesLoader.loadFactoryNames(type, classLoader));
    //进行实例化
    List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
                                                       classLoader, args, names);
    //根据取出的类中,@Order的顺序进行排序
    AnnotationAwareOrderComparator.sort(instances);
    return instances;
}

特别备注一下,从spring.factory中加载的ApplicationContextInitializer有:

org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer
org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer
org.springframework.boot.context.ContextIdApplicationContextInitializer
org.springframework.boot.context.config.DelegatingApplicationContextInitializer
org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer

加载的ApplicationListener有:

org.springframework.boot.autoconfigure.BackgroundPreinitializer
org.springframework.boot.ClearCachesApplicationListener
org.springframework.boot.builder.ParentContextCloserApplicationListener
org.springframework.boot.context.FileEncodingApplicationListener
org.springframework.boot.context.config.AnsiOutputApplicationListener
org.springframework.boot.context.config.ConfigFileApplicationListener
org.springframework.boot.context.config.DelegatingApplicationListener
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
org.springframework.boot.logging.ClasspathLoggingApplicationListener
org.springframework.boot.logging.LoggingApplicationListener
org.springframework.cloud.bootstrap.BootstrapApplicationListener
org.springframework.cloud.bootstrap.LoggingSystemShutdownListener
org.springframework.cloud.context.restart.RestartListener

启动SpringApplication

启动过程如下

public ConfigurableApplicationContext run(String... args) {
    //计时器
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    FailureAnalyzers analyzers = null;
    configureHeadlessProperty();
    //获取应用启动过程的监听器,SpringApplicationRunListener(注意不是ApplicationListener)
    SpringApplicationRunListeners listeners = getRunListeners(args);
    //触发监听器
    listeners.starting();
    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(
            args);
        //初始化环境变量,触发监听器
        ConfigurableEnvironment environment = prepareEnvironment(listeners,
                                                                 applicationArguments);
        //打印自定义banner
        Banner printedBanner = printBanner(environment);
        //实例化容器(AnnotationConfigEmbeddedWebApplicationContext)
        context = createApplicationContext();
        analyzers = new FailureAnalyzers(context);
        //容器前期准备
        prepareContext(context, environment, listeners, applicationArguments,
                       printedBanner);
        //刷新容器,注册钩子
        refreshContext(context);
        //执行容器中所有的ApplicationRunner和CommandLineRunner
        afterRefresh(context, applicationArguments);
        //触发监听器,hammerhead关闭和配置中心的连接
        listeners.finished(context, null);
        stopWatch.stop();
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass)
                .logStarted(getApplicationLog(), stopWatch);
        }
        return context;
    }
    catch (Throwable ex) {
        handleRunFailure(context, listeners, analyzers, ex);
        throw new IllegalStateException(ex);
    }
}

SpringApplicationRunListener也是从spring.factory中获取,具体如下。EventPublishingRunListener在实例化时,传入了SpringApplication获取的所有ApplicationListener,然后在调用starting方法时,发出ApplicationStartedEvent,让所有ApplicationListener处理(注意并非所有listener都会处理该事件);ImmutableConfigRunListener触发时hammerhead开始介入,获取配置文件。

org.springframework.boot.context.event.EventPublishingRunListener
com.cmbchina.drift.hammerhead.client.spring.ImmutableConfigRunListener

prepareEnvironment方法创建并配置了环境

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
    ApplicationArguments applicationArguments) {
    //创建StandardServletEnvironment实例
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    //设置启动参数,设置有效的profile
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    //触发监听器,广播事件,此处hammerhead开始打日志
    listeners.environmentPrepared(environment);
    if (!this.webEnvironment) {
        environment = new EnvironmentConverter(getClassLoader())
            .convertToStandardEnvironmentIfNecessary(environment);
    }
    return environment;
}

createApplicationContext方法创建了容器,实例化的是AnnotationConfigEmbeddedWebApplicationContext,实例化时会创建AnnotatedBeanDefinitionReader实例,调用AnnotationConfigUtils.registerAnnotationConfigProcessors方法,给容器注册了多个后置处理器,还有AnnotationAwareOrderComparator和ContextAnnotationAutowireCandidateResolver。

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, Object source) {

    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
    if (beanFactory != null) {
        if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
            beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
        }
        if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
            beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        }
    }

    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(8);

    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));
    }

    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
    if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
    if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition();
        try {
            def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                                                AnnotationConfigUtils.class.getClassLoader()));
        }
        catch (ClassNotFoundException ex) {
            throw new IllegalStateException(
                "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
        }
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
    }

    return beanDefs;
}

注册的后置处理器包括

ConfigurationClassPostProcessor
AutowiredAnnotationBeanPostProcessor
RequiredAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor
PersistenceAnnotationBeanPostProcessor
EventListenerMethodProcessor
DefaultEventListenerFactory

prepareContext方法对容器进行前期准备

private void prepareContext(ConfigurableApplicationContext context,
            ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
            ApplicationArguments applicationArguments, Banner printedBanner) {
    //设置环境
    context.setEnvironment(environment);
    //设置容器的beanNameGenerator和resourceLoader
    postProcessApplicationContext(context);
    //之前获取的ApplicationContextInitializer全部执行(参数是容器)
    applyInitializers(context);
    //监听器处理事件
    listeners.contextPrepared(context);
    if (this.logStartupInfo) {
        logStartupInfo(context.getParent() == null);
        logStartupProfileInfo(context);
    }
    //把执行参数的实例注册到容器
    context.getBeanFactory().registerSingleton("springApplicationArguments",applicationArguments);
    if (printedBanner != null) {
        context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
    }
    // Load the sources
    Set<Object> sources = getSources();
    Assert.notEmpty(sources, "Sources must not be empty");
    load(context, sources.toArray(new Object[sources.size()]));
    //ApplicationContext中获取的所有ApplicationListener,实现了ApplicationContextAware接口的把容器set进去
    //把所有ApplicationListener写入容器中
    listeners.contextLoaded(context);
}

refreshContext和afterRefresh流程涉及容器逻辑,会放在另一篇笔记中。

SpringApplication状态处理

SpringApplicationRunListener用于在SpringApplication处于不同生命周期。SpringBoot自己的实现为EventPublishingRunListener,每个生命周期会广播事件,然后依赖ApplicationListener处理这些事件。

生命周期---对应事件:

  • starting---ApplicationStartedEvent
  • environmentPrepared---ApplicationEnvironmentPreparedEvent
  • contextPrepared---无
  • contextLoaded---ApplicationPreparedEvent
  • finished---ApplicationFailedEvent、ApplicationReadyEvent

starting

environmentPrepared

1、BackgroundPreinitializer

会启动一个线程异步的进行预初始化,可以看到各种转换都在这里初始化,但是初始化后的东西没有引用的地方,不是很理解为什么要预初始化

private void performPreinitialization() {
    try {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                runSafely(new MessageConverterInitializer());
                runSafely(new MBeanFactoryInitializer());
                runSafely(new ValidationInitializer());
                runSafely(new JacksonInitializer());
                runSafely(new ConversionServiceInitializer());
                preinitializationComplete.countDown();
            }
            public void runSafely(Runnable runnable) {
                try {
                    runnable.run();
                }
                catch (Throwable ex) {
                    // Ignore
                }
            }

        }, "background-preinit");
        thread.start();
    }...
}

2、FileEncodingApplicationListener

比较file.encoding和spring.mandatoryFileEncoding是否一致,不一致会中断启动

3、AnsiOutputApplicationListener

控制彩色输出的,意义不大

4、ConfigFileApplicationListener

ConfigFileApplicationListener本身实现了EnvironmentPostProcessor接口,处理事件时,从spring.factory中取出所有的EnvironmentPostProcessor实现类,加上自己,触发所有的EnvironmentPostProcessor。

private void onApplicationEnvironmentPreparedEvent(
    ApplicationEnvironmentPreparedEvent event) {
    List<EnvironmentPostProcessor> postProcessors = loadPostProcessors();
    postProcessors.add(this);
    AnnotationAwareOrderComparator.sort(postProcessors);
    for (EnvironmentPostProcessor postProcessor : postProcessors) {
        postProcessor.postProcessEnvironment(event.getEnvironment(),
                                             event.getSpringApplication());
    }
}

List<EnvironmentPostProcessor> loadPostProcessors() {
    return SpringFactoriesLoader.loadFactories(EnvironmentPostProcessor.class,
                                               getClass().getClassLoader());
}

加载的所有EnvironmentPostProcessor列表如下:

org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor
org.springframework.cloud.client.HostInfoEnvironmentPostProcessor
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor
org.springframework.boot.context.config.ConfigFileApplicationListener
org.springframework.cloud.netflix.metrics.ServoEnvironmentPostProcessor
org.springframework.cloud.sleuth.autoconfig.TraceEnvironmentPostProcessor
org.springframework.cloud.sleuth.autoconfig.TraceStreamEnvironmentPostProcessor

5、DelegatingApplicationListener

如果有通过配置context.listener.classes指定监听器,DelegatingApplicationListener会实例化这个监听器,让其处理事件。也就是说DelegatingApplicationListener会把处理逻辑委托给配置的监听器。

6、ClasspathLoggingApplicationListener

打印classpath地址

7、BootstrapApplicationListener

处理bootstrap.properties文件 ,生成父容器,逻辑有点复杂。

8、LoggingSystemShutdownListener、LoggingApplicationListener

预初始化日志系统(logback啥的)

contextPrepared

contextLoaded

容器启动后触发的事件,之后会涉及到

finished

1、LoggingApplicationListener

清理日志系统

EnvironmentPostProcessor处理

1、SpringApplicationJsonEnvironmentPostProcessor

解析json格式的系统变量,用处不大

2、HostInfoEnvironmentPostProcessor

读取机器和网络信息,添加环境变量spring.cloud.client.hostname和spring.cloud.client.ipAddress

3、ConfigFileApplicationListener

处理配置文件,较为复杂, 可暂时不管

4、TraceEnvironmentPostProcessor

给日志添加trace配置

5、TraceStreamEnvironmentPostProcessor

trace相关

ApplicationContextInitializer处理

1、SharedMetadataReaderFactoryContextInitializer

向容器中注册了CachingMetadataReaderFactoryPostProcessor,这是一个BeanDefinitionRegistryPostProcessor实现。

2、AutoConfigurationReportLoggingInitializer

向容器注册了AutoConfigurationReportListener

3、ConfigurationWarningsApplicationContextInitializer

向容器注册了ConfigurationWarningsPostProcessor,这是一个BeanDefinitionRegistryPostProcessor实现。

4、ContextIdApplicationContextInitializer

给容器设置ID

5、DelegatingApplicationContextInitializer

如果有配置context.initializer.classes,会实例化配置的类。委托给了配置的initializer。

6、ServerPortInfoApplicationContextInitializer

给容器注册了一个匿名的ApplicationListener,用于设置端口号

相关文章

网友评论

    本文标题:SpringApplication

    本文链接:https://www.haomeiwen.com/subject/bbnprrtx.html