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

----紅色部分爲本節內容----

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