美文网首页
SpringApplication run方法 源码分析

SpringApplication run方法 源码分析

作者: BenjaminCool | 来源:发表于2019-12-08 20:36 被阅读0次

    java.awt.headless 参数说明

    spring.beaninfo.ignore

    “spring.beaninfo.ignore”,值为“true”表示跳过对BeanInfo类的搜索(通常用于首先没有为应用程序中的bean定义此类的情况)。

    考虑到所有BeanInfo元数据类,默认值为“false”,例如标准的Introspector.getBeanInfo(Class)调用。

    如果您遇到对不存在的BeanInfo类重复的ClassLoader访问,请考虑将此标志切换为“true”,以防此类访问在启动或延迟加载时很昂贵。

    SpringApplication的run方法

    
    public ConfigurableApplicationContext run(String... args) {
                     // 跑表,记录开始和结束时间
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
            ConfigurableApplicationContext context = null;
            Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    
                     // 一般是在程序开始激活headless模式,告诉程序,现在你要工作在Headless mode下,就不要指望硬件帮忙了,你得自力更生,依靠系统的计算能力模拟出这些特性来
            configureHeadlessProperty();
    
                   //  META-INF/spring.factories文件中获取SpringApplicationRunListener接口的实现类。
            SpringApplicationRunListeners listeners = getRunListeners(args);
            listeners.starting(); // SpringApplicationRunListener监听器开启监听
    
            try {
                           // 保存args参数
                ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
                           // 准备环境变量, 读取application.properties文件中的环境变量
                ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
    
                               // 跳过对不存在的BeanInfo类的搜索
                configureIgnoreBeanInfo(environment);
    
    
                             // 
                Banner printedBanner = printBanner(environment);
    
                             // 创建ApplicationContext, 即创建bean工厂
                context = createApplicationContext();
                exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
                        new Class[] { ConfigurableApplicationContext.class }, context);
                         //  将environment, listeners, applicationArguments, printedBanner等全部注册到bean工厂
                prepareContext(context, environment, listeners, applicationArguments, printedBanner);
    
                         // IoC容器开始创建bean实例
                refreshContext(context);
    
                      // IoC容器完成后
                afterRefresh(context, applicationArguments);
                stopWatch.stop();
                if (this.logStartupInfo) {
                    new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
                }
                listeners.started(context);
                         // 回调 ApplicationRunner,CommandLineRunner
                callRunners(context, applicationArguments);
            }
            catch (Throwable ex) {
                handleRunFailure(context, ex, exceptionReporters, listeners);
                throw new IllegalStateException(ex);
            }
    
            try {
                listeners.running(context);
            }
            catch (Throwable ex) {
                handleRunFailure(context, ex, exceptionReporters, null);
                throw new IllegalStateException(ex);
            }
            return context;
        }
    
    
    

    1、 SpringApplicationRunListener 监听器

    Listener for the {@link SpringApplication} {@code run} method.

    SpringApplicationRunListener用来监听SpringApplication的run方法;
    用来回调CommandLineRunner,ApplicationRunner 对象实例的

    2、根据key类型加载 META-INF/spring.factories 文件中的类。

    org/springframework/boot/spring-boot/2.1.4.RELEASE/spring-boot-2.1.4.RELEASE.jar!/META-INF/spring.factories

    SpringFactoriesLoader.loadFactoryNames(type, classLoader)
    根据key类型加载 META-INF/spring.factories 文件中的类。

    
    public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
            this.resourceLoader = resourceLoader; // null
            Assert.notNull(primarySources, "PrimarySources must not be null");
            this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
            this.webApplicationType = WebApplicationType.deduceFromClasspath();
    
    ////  根据key类型加载 META-INF/spring.factories 文件中的ApplicationContextInitializer类。
            setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    
    //根据key类型加载 META-INF/spring.factories 文件中的ApplicationListener类。
            setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
            this.mainApplicationClass = deduceMainApplicationClass();
        }
    
    image.png

    3、SpringApplication 加载META-INF/spring.factories文件中执行类型的key的过程

        private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
            ClassLoader classLoader = getClassLoader(); // 获取类加载器,默认当前线程的类加载器
    
            // Use names and ensure unique to protect against duplicates
    // SpringFactoriesLoader根据type类型(key类型)加载加载spring.factories文件的类
            Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
    
    // 对获取到的类创建对象实例
            List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
    
    // 根据@Order或@Priority对对象实例排序
            AnnotationAwareOrderComparator.sort(instances);
    
            return instances;//返回对象实例
        }
    
    

    自动配置启动流程

    ConfigurationClassPostProcessor

    ConfigurationClassParser

    SpringApplication执行run方法

    run方法执行 AbstractApplicationContext.refresh方法

    在refresh方法中, 实现了对ConfigurationClassParser的调用。

    AbstractApplicationContext.refresh方法

    AbstractApplicationContext.refresh

    // Invoke factory processors registered as beans in the context.
    invokeBeanFactoryPostProcessors(beanFactory);

    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

    image.png image.png

    ConfigurationClassPostProcessor

    image.png image.png image.png image.png

    ConfigurationClassParser


    image.png

    AnnotationConfigReactiveWebServerApplicationContext

    创建是AnnotationConfigReactiveWebServerApplicationContext

    image.png

    BeanFactoryPostProcessor可以与bean定义交互并修改它们,但不能与bean实例交互。这样做可能会导致过早的bean实例化,违反容器并导致意外的副作用。如果需要bean实例交互,请考虑实现beanpstprocessor。

    image.png image.png image.png image.png

    相关文章

      网友评论

          本文标题:SpringApplication run方法 源码分析

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