Springboot Code (二)项目启动

前一文学习了项目启动的流程:

(一)new SpringApplication

  1. 配置source和web环境;
  2. 创建初始化构造器和应用监听器;
  3. 配置应用的主方法所在类;

(二)run 第一部分

  1. 初始化计时、启动上下文、设置系统参数;
  2. 初始化监听器列表;
  3. 发布springboot开始启动事件(从applicationListeners中过滤出4个能监听ApplicationStartingEvent事件的,并启动它们)

继续下面的学习这个方法:

     public ConfigurableApplicationContext run(String... args) {
        //1、StopWatch简单的看成一个stop watch的机制,保存stop的记录信息。
        //初始化一个计时器,并开始计时
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        //初始化启动上下文
        DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
        ConfigurableApplicationContext context = null;
        
        //2、configureHeadlessProperty即配置headless模式,这种模式是一种系统缺少显示设备、键盘和鼠标外设的情况模式。
        this.configureHeadlessProperty();

        //3、SpringApplicationListeners为SpringApplicationRunListener接口实现集合(创建SpringApplicationRunListener初始化构造器)初始化监听器列表
        //可以理解这个接口就是在spring启动整个过程都需要回调这些listener
        //debug能发现,拿到了一个名为EventPublishingRunListener(RunListener构造方法中关联上了全部applicationListener),这个就是用来进行触发publishEvent的被观察者
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        //启动EventPublishingRunListener,从而过滤并启动相关Listener
        listeners.starting(bootstrapContext, this.mainApplicationClass);

        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            //4、ConfigurableEnvironment为配置环境对象,简单理解所有的配置信息汇总在这个对象中
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            this.configureIgnoreBeanInfo(environment);

            //5、Banner就是我们常在控制台输出的画面横幅,可以使用图片或者文本进行替换
            Banner printedBanner = this.printBanner(environment);

            //6、ConfigurableApplicationContext根据webApp…Type进行构造的上下文对象
            context = this.createApplicationContext();
            context.setApplicationStartup(this.applicationStartup);

            //7、接下来进入关键步骤的第一步:prepareContext,准备容器阶段,将执行所有的initializers逻辑,做初始化准备操作。
            this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);

            //8、refreshContext,可以理解成容器初始化节点,将执行bean的创建和实例化。
            this.refreshContext(context);

            //9、afterRefresh,容器后处理, 可以看到会找到ApplicationRunner和CommandLineRunner的实现类并执行。但从2.x版本来看,似乎这个方法是个空方法,applicationRun和commandRun移到启动最后。
            this.afterRefresh(context, applicationArguments);

            //10、然后根据stopwatch打印出启动时间
            stopWatch.stop();
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }

            listeners.started(context);
             
            //11、这里调用ApplicationRunner和CommandLineRunner的实现类
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {
            this.handleRunFailure(context, var10, listeners);
            throw new IllegalStateException(var10);
        }

        try {
            listeners.running(context);
            return context;
        } catch (Throwable var9) {
            this.handleRunFailure(context, var9, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var9);
        }
    }

回到正题,继续run方法的第二部分try部分:(当前以最新SpringbootV2.4.4版本进行学习)

try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            //4、ConfigurableEnvironment为配置环境对象,简单理解所有的配置信息汇总在这个对象中
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            this.configureIgnoreBeanInfo(environment);

ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

args参数在启动程序时是可配置的,不配置为null,下面跟进一下方法(将深入方法揉到一起)简单命令行解析器解析参数,最后以PropertySource对象形式赋值给source。DefaultApplicationArguments就是保存了两种形式的参数值

    public DefaultApplicationArguments(String... args) {
        Assert.notNull(args, "Args must not be null");
        this.source = new DefaultApplicationArguments.Source(args);
        this.args = args;
    }
    /**
    *跟进source构造方法
    **/
    private static class Source extends SimpleCommandLinePropertySource {
        Source(String[] args) {
            super(args);
        }
        ... ...
    }
    /**
    *跟进父类构造方法,将处理结果赋值给父类,即PropertySource对象
    **/
    public class SimpleCommandLinePropertySource extends CommandLinePropertySource<CommandLineArgs> {
        public SimpleCommandLinePropertySource(String... args) {
            super((new SimpleCommandLineArgsParser()).parse(args));
        }
        ... ...
    }
    /**
    *跟进parse方法(命令行解析器,将启动参数字符串截取出key与value)
    **/
    public CommandLineArgs parse(String... args) {
        CommandLineArgs commandLineArgs = new CommandLineArgs();
        String[] var3 = args;
        int var4 = args.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            String arg = var3[var5];
            if (arg.startsWith("--")) {
                String optionText = arg.substring(2);
                String optionValue = null;
                int indexOfEqualsSign = optionText.indexOf(61);
                String optionName;
                if (indexOfEqualsSign > -1) {
                    optionName = optionText.substring(0, indexOfEqualsSign);
                    optionValue = optionText.substring(indexOfEqualsSign + 1);
                } else {
                    optionName = optionText;
                }

                if (optionName.isEmpty()) {
                    throw new IllegalArgumentException("Invalid argument syntax: " + arg);
                }

                commandLineArgs.addOptionArg(optionName, optionValue);
            } else {
                commandLineArgs.addNonOptionArg(arg);
            }
        }

        return commandLineArgs;
    }

下面执行 ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);逐行来看

        private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
       ====> ConfigurableEnvironment environment = this.getOrCreateEnvironment();
             this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
             ConfigurationPropertySources.attach((Environment)environment);
             listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);
             DefaultPropertiesPropertySource.moveToEnd((ConfigurableEnvironment)environment);
             this.configureAdditionalProfiles((ConfigurableEnvironment)environment);
             this.bindToSpringApplication((ConfigurableEnvironment)environment);
            if (!this.isCustomEnvironment) {
               environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
            }

            ConfigurationPropertySources.attach((Environment)environment);
            return (ConfigurableEnvironment)environment;
        }

        private ConfigurableEnvironment getOrCreateEnvironment() {
            if (this.environment != null) {
                return this.environment;
            } else {
                switch(this.webApplicationType) {
                case SERVLET:
                    return new StandardServletEnvironment();
                case REACTIVE:
                    return new StandardReactiveWebEnvironment();
                default:
                    return new StandardEnvironment();
                }
            }
        }

        public class StandardServletEnvironment extends StandardEnvironment implements ConfigurableWebEnvironment {
            public static final String SERVLET_CONTEXT_PROPERTY_SOURCE_NAME = "servletContextInitParams";
            public static final String SERVLET_CONFIG_PROPERTY_SOURCE_NAME = "servletConfigInitParams";
            public static final String JNDI_PROPERTY_SOURCE_NAME = "jndiProperties";

            public StandardServletEnvironment() {
            }

            protected StandardServletEnvironment(MutablePropertySources propertySources) {
                super(propertySources);
            }

            protected void customizePropertySources(MutablePropertySources propertySources) {
                propertySources.addLast(new StubPropertySource("servletConfigInitParams"));
                propertySources.addLast(new StubPropertySource("servletContextInitParams"));
                if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
                    propertySources.addLast(new JndiPropertySource("jndiProperties"));
               }
                super.customizePropertySources(propertySources);
            }
    
            public void initPropertySources(@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
                WebApplicationContextUtils.initServletPropertySources(this.getPropertySources(), servletContext, servletConfig);
            }
        }

        /**
        *调用父类customizeProperty方法
        **/
        protected void customizePropertySources(MutablePropertySources propertySources) {
            propertySources.addLast(new PropertiesPropertySource("systemProperties", this.getSystemProperties()));
            propertySources.addLast(new SystemEnvironmentPropertySource("systemEnvironment", this.getSystemEnvironment()));
        }

下面来看下propertySources对象是怎么保存的,原来是用list保存了PropertySource对象(StandardEnvironment的customizePropertiesSources中加入systemEnvironment和systemProperties,StandardServletEnvironment的customizePropertiesSources中加入servletContextInitParams和servletConfigInitParams)

    public class MutablePropertySources implements PropertySources {
        private final List<PropertySource<?>> propertySourceList;

        public MutablePropertySources() {
            this.propertySourceList = new CopyOnWriteArrayList();
        }
    ... ...
    }

        private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
             ConfigurableEnvironment environment = this.getOrCreateEnvironment();
       ====> this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
             ConfigurationPropertySources.attach((Environment)environment);
             listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);
             DefaultPropertiesPropertySource.moveToEnd((ConfigurableEnvironment)environment);
             this.configureAdditionalProfiles((ConfigurableEnvironment)environment);
             this.bindToSpringApplication((ConfigurableEnvironment)environment);
            if (!this.isCustomEnvironment) {
               environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
            }

            ConfigurationPropertySources.attach((Environment)environment);
            return (ConfigurableEnvironment)environment;
        }
    protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
        //ConversionService在前面Listener有执行过初始化(上一章节),此时为true加载到容器中
        //包含一些基本类型的转换等,都放到environment中
        if (this.addConversionService) {
            // 加载一些转换器和格式化器,下面跟进代码
            ConversionService conversionService = ApplicationConversionService.getSharedInstance();
            environment.setConversionService((ConfigurableConversionService)conversionService);
        }

        //配置属性(defaultProperties和commandLineProperties两部分)
        this.configurePropertySources(environment, args);
        //内容空,之前版本是加载spring.profile.active配置的(应该是版本导致不在这里处理了)
        this.configureProfiles(environment, args);
    }

    public static ConversionService getSharedInstance() {
        ApplicationConversionService sharedInstance = ApplicationConversionService.sharedInstance;
        if (sharedInstance == null) {
            Class var1 = ApplicationConversionService.class;
            synchronized(ApplicationConversionService.class) {
                sharedInstance = ApplicationConversionService.sharedInstance;
                if (sharedInstance == null) {
                    sharedInstance = new ApplicationConversionService();
                    ApplicationConversionService.sharedInstance = sharedInstance;
                }
            }
        }

        return sharedInstance;
    }

    public ApplicationConversionService(){
        ... ...
        configure(this);
    }

    public static void configure(FormatterRegistry registry) {
        DefaultConversionService.addDefaultConverters(registry);
        DefaultFormattingConversionService.addDefaultFormatters(registry);
        addApplicationFormatters(registry);
        addApplicationConverters(registry);
    }

    public static void addApplicationConverters(ConverterRegistry registry) {
        addDelimitedStringConverters(registry);
        registry.addConverter(new StringToDurationConverter());
        registry.addConverter(new DurationToStringConverter());
        registry.addConverter(new NumberToDurationConverter());
        registry.addConverter(new DurationToNumberConverter());
        registry.addConverter(new StringToPeriodConverter());
        registry.addConverter(new PeriodToStringConverter());
        registry.addConverter(new NumberToPeriodConverter());
        registry.addConverter(new StringToDataSizeConverter());
        registry.addConverter(new NumberToDataSizeConverter());
        registry.addConverter(new StringToFileConverter());
        registry.addConverter(new InputStreamSourceToByteArrayConverter());
        registry.addConverterFactory(new LenientStringToEnumConverterFactory());
        registry.addConverterFactory(new LenientBooleanToEnumConverterFactory());
        if (registry instanceof ConversionService) {
            addApplicationConverters(registry, (ConversionService)registry);
        }

    }

    private static void addApplicationConverters(ConverterRegistry registry, ConversionService conversionService) {
        registry.addConverter(new CharSequenceToObjectConverter(conversionService));
    }

    public static void addDelimitedStringConverters(ConverterRegistry registry) {
        ConversionService service = (ConversionService)registry;
        registry.addConverter(new ArrayToDelimitedStringConverter(service));
        registry.addConverter(new CollectionToDelimitedStringConverter(service));
        registry.addConverter(new DelimitedStringToArrayConverter(service));
        registry.addConverter(new DelimitedStringToCollectionConverter(service));
    }

    public static void addApplicationFormatters(FormatterRegistry registry) {
        registry.addFormatter(new CharArrayFormatter());
        registry.addFormatter(new InetAddressFormatter());
        registry.addFormatter(new IsoOffsetFormatter());
    }
        private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
             ConfigurableEnvironment environment = this.getOrCreateEnvironment();
             this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
       ====> ConfigurationPropertySources.attach((Environment)environment);
             listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);
             DefaultPropertiesPropertySource.moveToEnd((ConfigurableEnvironment)environment);
             this.configureAdditionalProfiles((ConfigurableEnvironment)environment);
             this.bindToSpringApplication((ConfigurableEnvironment)environment);
            if (!this.isCustomEnvironment) {
               environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
            }

            ConfigurationPropertySources.attach((Environment)environment);
            return (ConfigurableEnvironment)environment;
        }
    //检查environment中propertySource中没有configurationProperties,并添加configurationProperties
    //如果有configurationProperties,删除后重新添加configurationProperties
    public static void attach(Environment environment) {
        Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
        MutablePropertySources sources = ((ConfigurableEnvironment)environment).getPropertySources();
        PropertySource<?> attached = sources.get("configurationProperties");
        if (attached != null && attached.getSource() != sources) {
            sources.remove("configurationProperties");
            attached = null;
        }

        if (attached == null) {
            sources.addFirst(new ConfigurationPropertySourcesPropertySource("configurationProperties", new SpringConfigurationPropertySources(sources)));
        }

    }

debug发现environment中已经包含了5个propertySource

        private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
             ConfigurableEnvironment environment = this.getOrCreateEnvironment();
             this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
             ConfigurationPropertySources.attach((Environment)environment);
       ====> listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);
             DefaultPropertiesPropertySource.moveToEnd((ConfigurableEnvironment)environment);
             this.configureAdditionalProfiles((ConfigurableEnvironment)environment);
             this.bindToSpringApplication((ConfigurableEnvironment)environment);
            if (!this.isCustomEnvironment) {
               environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
            }

            ConfigurationPropertySources.attach((Environment)environment);
            return (ConfigurableEnvironment)environment;
        }
    void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
        this.doWithListeners("spring.boot.application.environment-prepared", (listener) -> {
            listener.environmentPrepared(bootstrapContext, environment);
        });
    }

此处listener还是前文提到的runListener,此处和前文过滤并执行Listener逻辑相似。下面看EventPublishingRunListener中environmentPrepared方法

    public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
        this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(bootstrapContext, this.application, this.args, environment));
    }

    public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) {
        ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
        Executor executor = this.getTaskExecutor();
        Iterator var5 = this.getApplicationListeners(event, type).iterator();

        while(var5.hasNext()) {
            ApplicationListener<?> listener = (ApplicationListener)var5.next();
            if (executor != null) {
                executor.execute(() -> {
                    this.invokeListener(listener, event);
                });
            } else {
                this.invokeListener(listener, event);
            }
        }

    }

    protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {
        Object source = event.getSource();
        Class<?> sourceType = source != null ? source.getClass() : null;
        AbstractApplicationEventMulticaster.ListenerCacheKey cacheKey = new AbstractApplicationEventMulticaster.ListenerCacheKey(eventType, sourceType);
        AbstractApplicationEventMulticaster.CachedListenerRetriever newRetriever = null;
        AbstractApplicationEventMulticaster.CachedListenerRetriever existingRetriever = (AbstractApplicationEventMulticaster.CachedListenerRetriever)this.retrieverCache.get(cacheKey);
        if (existingRetriever == null && (this.beanClassLoader == null || ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
            newRetriever = new AbstractApplicationEventMulticaster.CachedListenerRetriever();
            existingRetriever = (AbstractApplicationEventMulticaster.CachedListenerRetriever)this.retrieverCache.putIfAbsent(cacheKey, newRetriever);
            if (existingRetriever != null) {
                newRetriever = null;
            }
        }

        if (existingRetriever != null) {
            Collection<ApplicationListener<?>> result = existingRetriever.getApplicationListeners();
            if (result != null) {
                return result;
            }
        }

        return this.retrieveApplicationListeners(eventType, sourceType, newRetriever);
    }

    private Collection<ApplicationListener<?>> retrieveApplicationListeners(ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable AbstractApplicationEventMulticaster.CachedListenerRetriever retriever) {
        List<ApplicationListener<?>> allListeners = new ArrayList();
        Set<ApplicationListener<?>> filteredListeners = retriever != null ? new LinkedHashSet() : null;
        Set<String> filteredListenerBeans = retriever != null ? new LinkedHashSet() : null;
        LinkedHashSet listeners;
        LinkedHashSet listenerBeans;
        synchronized(this.defaultRetriever) {
            listeners = new LinkedHashSet(this.defaultRetriever.applicationListeners);
            listenerBeans = new LinkedHashSet(this.defaultRetriever.applicationListenerBeans);
        }

        Iterator var9 = listeners.iterator();

        while(var9.hasNext()) {
            ApplicationListener<?> listener = (ApplicationListener)var9.next();
            if (this.supportsEvent(listener, eventType, sourceType)) {
                if (retriever != null) {
                    filteredListeners.add(listener);
                }

                allListeners.add(listener);
            }
        }

        if (!listenerBeans.isEmpty()) {
            ConfigurableBeanFactory beanFactory = this.getBeanFactory();
            Iterator var16 = listenerBeans.iterator();

            while(var16.hasNext()) {
                String listenerBeanName = (String)var16.next();

                try {
                    if (this.supportsEvent(beanFactory, listenerBeanName, eventType)) {
                        ApplicationListener<?> listener = (ApplicationListener)beanFactory.getBean(listenerBeanName, ApplicationListener.class);
                        if (!allListeners.contains(listener) && this.supportsEvent(listener, eventType, sourceType)) {
                            if (retriever != null) {
                                if (beanFactory.isSingleton(listenerBeanName)) {
                                    filteredListeners.add(listener);
                                } else {
                                    filteredListenerBeans.add(listenerBeanName);
                                }
                            }

                            allListeners.add(listener);
                        }
                    } else {
                        Object listener = beanFactory.getSingleton(listenerBeanName);
                        if (retriever != null) {
                            filteredListeners.remove(listener);
                        }

                        allListeners.remove(listener);
                    }
                } catch (NoSuchBeanDefinitionException var13) {
                }
            }
        }

        AnnotationAwareOrderComparator.sort(allListeners);
        if (retriever != null) {
            if (filteredListenerBeans.isEmpty()) {
                retriever.applicationListeners = new LinkedHashSet(allListeners);
                retriever.applicationListenerBeans = filteredListenerBeans;
            } else {
                retriever.applicationListeners = filteredListeners;
                retriever.applicationListenerBeans = filteredListenerBeans;
            }
        }

        return allListeners;
    }

最后得到事件监听器有6个,并开始执行invokeListener方法(即执行listener监听事件方法onApplicationEvent)

    // 看一下EnvironmentPostProcessorApplicationListener

    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ApplicationEnvironmentPreparedEvent) {
            this.onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent)event);
        }

        if (event instanceof ApplicationPreparedEvent) {
            this.onApplicationPreparedEvent((ApplicationPreparedEvent)event);
        }

        if (event instanceof ApplicationFailedEvent) {
            this.onApplicationFailedEvent((ApplicationFailedEvent)event);
        }

    }

    private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {
        ConfigurableEnvironment environment = event.getEnvironment();
        SpringApplication application = event.getSpringApplication();
        // getEnvironmentPostProcessors返回全部环境后置处理器(spring.factories中获取)
        Iterator var4 = this.getEnvironmentPostProcessors(event.getBootstrapContext()).iterator();

        while(var4.hasNext()) {
            EnvironmentPostProcessor postProcessor = (EnvironmentPostProcessor)var4.next();
            postProcessor.postProcessEnvironment(environment, application);
        }

    }

debug发现EnvironmentPostProcessorApplicationListener中ConfigDataEnvironmentPostProcessor就将spring.profile.active值配置给了参数environment.activeProfiles,方便后续加载activeProfiles里的内容。刚刚未做任何处理的空方法this.configureProfiles(environment, args),在新版中方法内容迁移到了后置处理器中去处理了。也在这里更新了propertyList[8个值]。其他监听器及后置处理器不再赘述。

        private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
             ConfigurableEnvironment environment = this.getOrCreateEnvironment();
             this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
             ConfigurationPropertySources.attach((Environment)environment);
             listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);
       ====> DefaultPropertiesPropertySource.moveToEnd((ConfigurableEnvironment)environment);
             this.configureAdditionalProfiles((ConfigurableEnvironment)environment);
             this.bindToSpringApplication((ConfigurableEnvironment)environment);
            if (!this.isCustomEnvironment) {
               environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
            }

            ConfigurationPropertySources.attach((Environment)environment);
            return (ConfigurableEnvironment)environment;
        }
    public static void moveToEnd(ConfigurableEnvironment environment) {
        moveToEnd(environment.getPropertySources());
    }

    // 去除environment.propertySources[list|5个值]中defaultProperties
    public static void moveToEnd(MutablePropertySources propertySources) {
        PropertySource<?> propertySource = propertySources.remove("defaultProperties");
        if (propertySource != null) {
            propertySources.addLast(propertySource);
        }
    }
    private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
       ConfigurableEnvironment environment = this.getOrCreateEnvironment();
       this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
       ConfigurationPropertySources.attach((Environment)environment);
       listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);
       DefaultPropertiesPropertySource.moveToEnd((ConfigurableEnvironment)environment);
 ====> this.configureAdditionalProfiles((ConfigurableEnvironment)environment);
       this.bindToSpringApplication((ConfigurableEnvironment)environment);
       if (!this.isCustomEnvironment) {
          environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
       }

       ConfigurationPropertySources.attach((Environment)environment);
       return (ConfigurableEnvironment)environment;
    }

这里检查additionalProfiles是否已经加载过了profiles,前面已经加载了,继续向下执行,将环境绑定到application中,环境变量类型校验与转换,最后经转换后防止丢配置进行环境对象刷新(重置environment.propertySource[list0]的configurationProperties)

进入run方法的主流程 this.configureIgnoreBeanInfo(environment);

配置忽略某些bean,配置后可以debug到下图

    private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
        if (System.getProperty("spring.beaninfo.ignore") == null) {
            Boolean ignore = (Boolean)environment.getProperty("spring.beaninfo.ignore", Boolean.class, Boolean.TRUE);
            System.setProperty("spring.beaninfo.ignore", ignore.toString());
        }
    }

进入run方法的主流程 Banner printedBanner = this.printBanner(environment);

private Banner printBanner(ConfigurableEnvironment environment) {
    if (this.bannerMode == Mode.OFF) {
        return null;
    } else {
        ResourceLoader resourceLoader = this.resourceLoader != null ? this.resourceLoader : new DefaultResourceLoader((ClassLoader)null);
        SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter((ResourceLoader)resourceLoader, this.banner);
        return this.bannerMode == Mode.LOG ? bannerPrinter.print(environment, this.mainApplicationClass, logger) : bannerPrinter.print(environment, this.mainApplicationClass, System.out);
    }
}

 

汇总一下:

(一)new SpringApplication

  1. 配置source和web环境;
  2. 创建初始化构造器和应用监听器;
  3. 配置应用的主方法所在类;

(二)run 第一二部分

  1. 初始化计时stopWatch、启动上下文bootstrapContext、设置系统参数headless;
  2. 初始化监听器列表SpringApplicationRunListeners;
  3. 发布springboot开始启动事件(从applicationListeners中过滤出4个能监听ApplicationStartingEvent事件的,并启动它们)
  4. 装配命令行参数applicationArguments(对象中装载4个propertySource);
  5. 准备应用程序运行的环境ConfigurableEnvironment(从applicationListeners中过滤出6个能监听ApplicationEnvironmentPreparedEvent事件的,并启动它们。监听器中关联启动了一些后置处理器处理数据,最终目的是为应用环境做准备)
  6. 配置忽略bean和打印banner

----红色部分为本节内容----

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章