Spring Boot入門教程(五):@SpringBootApplication

自動配置

Spring使用@Configuration作爲配置的註解,其實這個註解沒什麼東西,使用@Component作爲元註解,和@Service、@Repository差不多,只是起了一個新的名字,表示了更具體的含義,當Spring發現某個類使用了@Configuration標註了,就去將該類下使用@Bean註解的方法創建bean並放入到容器中。

@Configuration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    @AliasFor(annotation = Component.class)
    String value() default "";
}

關於自動配置,我們既可以使用系統提供好的默認配置,也可以使用自己的配置,那麼究竟何時會使用系統自定義的配置呢?是通過@ConditionalOnXxx(@ConditionalOnClass、@ConditionalOnMissingBean等)來實現的,該類型的註解都是基於@Conditional註解來實現的

關於自動配置可以通過瀏覽spring-boot-autoconfigure.jar下的spring.factories配置文件,查看所有的自動配置

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\

理解Spring Boot的自動配置先要理解@Conditional註解

@Bean: 將當前對象放入到Spring的IOC容器中來管理
@Conditional:滿足特定條件時纔會創建一個Bean放入到IOC容器,SpringBoot就是利用這個特性進行自動配置的。

@FunctionalInterface
public interface Condition {
    boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}

寫一個小示例來理解下@Conditional的作用: 在不同的操作系統中列舉某個目錄下的文件的命令是不同的,類unix系統使用ls命令,windows命令使用dir命令。現在定義兩個類分別對應着兩種系統,只將當前系統對應的類放入到IOC容器中,另一個類不放進IOC中。

OnWindowsCondition

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class OnWindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return context.getEnvironment().getProperty("os.name").contains("Windows");
    }
}

OnUnixCondition

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class OnUnixCondition implements Condition{
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        String osName = conditionContext.getEnvironment().getProperty("os.name");
        return osName.contains("unix") || osName.contains("linux") || osName.contains("Mac OS X");
    }
}

ListService

public interface ListService {
    public String showListCmd();
}

public class WindowsListService implements ListService {
    @Override
    public String showListCmd() {
        return "dir";
    }
}
public class UnixListService implements ListService {
    @Override
    public String showListCmd() {
        return "ls";
    }
}

ListSesrviceConfig
使用@Bean來標註將對象放入到IOC容器中,但是如果有@Conditional只有在滿足條件註解纔會將對象放入到IOC容器中,不滿足就不會放入容器。

@Configuration
public class ListSesrviceConfig {

    @Bean
    @Conditional(OnWindowsCondition.class)
    public ListService windowsListService(){
        return new WindowsListService();
    }

    @Bean
    @Conditional(OnUnixCondition.class)
    public ListService unixListService(){
        return new UnixListService();
    }
}
public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(ListSesrviceConfig.class);
        Map<String, ListService> beansOfType = context.getBeansOfType(ListService.class);

        ListService listService = context.getBean(ListService.class);
        // Mac OS X系統下的列表命令爲:ls
        System.out.println(context.getEnvironment().getProperty("os.name")
                + "系統下的列表命令爲:" + listService.showListCmd());
    }
}

運行結果:可以看到main方法中beansOfType的只有一個鍵值對:UnixListService,而WindowsListService並沒有放入到容器中。

  • @ConditionalOnXxx都是組合@Conditional元註解,使用了不同的條件Condition

  • @ConditionalOnBean:當容器裏有指定Bean的條件下

  • @ConditionalOnClass:當類路徑下有指定類的條件下

  • @ConditionalOnExpression:基於SpEL表達式作爲判斷條件

  • @ConditionalOnJava:基於JV版本作爲判斷條件

  • @ConditionalOnJndi:在JNDI存在的條件下差在指定的位置

  • @ConditionalOnMissingBean:當容器裏沒有指定Bean的情況下

  • @ConditionalOnMissingClass:當類路徑下沒有指定類的條件下

  • @ConditionalOnNotWebApplication:當前項目不是Web項目的條件下

  • @ConditionalOnProperty:指定的屬性是否有指定的值

  • @ConditionalOnResource:類路徑是否有指定的資源

  • @ConditionalOnSingleCandidate:當指定Bean在容器中只有一個,或者雖然有多個但是指定首選Bean

  • @ConditionalOnWebApplication:當前項目是Web項目的條件下


@SpringBootApplication

啓動入口:Application

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

@SpringBootApplication 中最重要的註解有三個:@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan,其中@SpringBootConfiguration實際上是@Configuration。即@SpringBootApplication是一個複合註解,包括三個:

  • @Configuration
  • @ComponentScan
  • @EnableAutoConfiguration
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
}
@Configuration
public @interface SpringBootConfiguration {

}

將@SpringBootApplication註解替換成其等價的三個註解是完全的相等的,可以啓動並正常訪問。

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

@ComponentScan

組件掃描這個是我們最熟悉的註解,即使沒有使用過註解也經常在spring的配置文件中使用過<context:component-scan base-package=“com.xxx.xxx”/>, 組件掃描就是掃描指定的包下的類,並加載符合條件的組件(比如@Component、@Service、@Repository等)或者bean定義,最終將這些bean定義加載到IoC容器中,如果不指定basePackage則默認Spring框架實現會從聲明@ComponentScan所在類的package進行掃描。Spring Boot 中的@ComponentScan沒有指定basePackage,所以會從.下開始掃描,所以,一般Application類要放在groupId.artifactId包下。

@Configuration

@Configuration 就是指的Java Config(Java 配置),是一個Ioc容器類,相當於傳統項目中見到的一個spring 的xml配置文件。

一個空Java Config類 相當於一個空的xml配置文件,都是用來作爲配置bean的容器

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
       default-lazy-init="true">
    <!--bean定義-->
</beans>
@Configuration
public class XxxConfiguration{
    //bean定義
}

在xml中配置一個bean,就等價於在Java Config中定義一個方法,使用@Bean註解就相當於xml中的bean標籤,bean標籤中的id就是方法的名稱, bean標籤中的class就是Java Config中的返回值,Java Config中的方法的內部就是創建一個實例

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
       default-lazy-init="true">
    <!--bean定義-->
    <bean id="xxxService" class="com.xxx.yyy.impl.XxxServiceImpl">
        ...
    </bean>
</beans>
@Configuration
public class XxxConfiguration{
    @Bean
    public XxxService xxxService(){
        return new XxxServiceImpl();
    }
}

xml中一個bean的屬性需要引用另一個bean時,在Java Config中需要先定義出需要的依賴類,然後通過Setter方法或者構造方法給依賴的屬性賦值,從而創建出一個完整的實例。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
       default-lazy-init="true">
    <!--bean定義-->
    <bean id="xxxService" class="com.xxx.yyy.impl.XxxServiceImpl">
        <propery name ="yyyService" ref="yyyService" />
    </bean>

    <bean id="yyyService" class="com.xxx.yyy.impl.YyyServiceImpl"/>
</beans>
@Configuration
public class XxxConfiguration{
    @Bean
    public XxxService xxxService(){
        // XxxService xxxService = new XxxServiceImpl();
        // xxxService.setYyyService(yyyService());

        return new XxxServiceImpl(yyyService());
    }

    @Bean
    public YyyService yyyService(){
        return new YyyServiceImpl();
    }
}

一個Java Config就相當於一個Spring配置文件,Java配置和spring配置文件兩者都是一種Ioc容器,都是爲了讓Spring去加載定義好的類,放入到IoC容器中。

@EnableAutoConfiguration

@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
}

Spring 中有很多以Enable開頭的註解,其作用就是藉助@Import來收集並註冊特定場景相關的bean,並加載到IoC容器。@EnableAutoConfiguration就是藉助@Import來收集所有符合自動配置條件的bean定義,並加載到IoC容器。

@EnableAutoConfiguration通過@Import中的AutoConfigurationImportSelector,可以幫助SpringBoot應用將所有符合條件的@Configuration配置都加載到當前SpringBoot創建並使用的IoC容器(ApplicationContext)。

在這裏插入圖片描述

SpringFactoriesLoader

主要功能就是從指定的配置文件META-INF/spring.factories加載配置。配合@EnableAutoConfiguration使用的話,它更多是提供一種配置查找的功能支持,即根據@EnableAutoConfiguration的完整類名org.springframework.boot.autoconfigure.EnableAutoConfiguration作爲查找的Key,獲取對應的一組@Configuration類

public abstract class SpringFactoriesLoader {
    public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
    public static <T> List<T> loadFactories(Class<T> factoryClass, @Nullable ClassLoader classLoader) {

 }

    public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
}

spring.factories

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.core.ReactorCoreAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration

@EnableAutoConfiguration自動配置就是從classpath中搜尋所有的META-INF/spring.factories配置文件,並將其中org.springframework.boot.autoconfigure.EnableutoConfiguration對應的配置項通過反射(Java Refletion)實例化爲對應的標註了@Configuration的JavaConfig形式的IoC容器配置類,然後彙總爲一個並加載到IoC容器。

SpringApplication的run方法的實現是我們本次旅程的主要線路,該方法的主要流程大體可以歸納如下:

1) 如果我們使用的是SpringApplication的靜態run方法,那麼,這個方法裏面首先要創建一個SpringApplication對象實例,然後調用這個創建好的SpringApplication的實例方法。在SpringApplication實例初始化的時候,它會提前做幾件事情:

根據classpath裏面是否存在某個特徵類(org.springframework.web.context.ConfigurableWebApplicationContext)來決定是否應該創建一個爲Web應用使用的ApplicationContext類型。
使用SpringFactoriesLoader在應用的classpath中查找並加載所有可用的ApplicationContextInitializer。
使用SpringFactoriesLoader在應用的classpath中查找並加載所有可用的ApplicationListener。
推斷並設置main方法的定義類。
2) SpringApplication實例初始化完成並且完成設置後,就開始執行run方法的邏輯了,方法執行伊始,首先遍歷執行所有通過SpringFactoriesLoader可以查找到並加載的SpringApplicationRunListener。調用它們的started()方法,告訴這些SpringApplicationRunListener,“嘿,SpringBoot應用要開始執行咯!”。

3) 創建並配置當前Spring Boot應用將要使用的Environment(包括配置要使用的PropertySource以及Profile)。

4) 遍歷調用所有SpringApplicationRunListener的environmentPrepared()的方法,告訴他們:“當前SpringBoot應用使用的Environment準備好了咯!”。

5) 如果SpringApplication的showBanner屬性被設置爲true,則打印banner。

6) 根據用戶是否明確設置了applicationContextClass類型以及初始化階段的推斷結果,決定該爲當前SpringBoot應用創建什麼類型的ApplicationContext並創建完成,然後根據條件決定是否添加ShutdownHook,決定是否使用自定義的BeanNameGenerator,決定是否使用自定義的ResourceLoader,當然,最重要的,將之前準備好的Environment設置給創建好的ApplicationContext使用。

7) ApplicationContext創建好之後,SpringApplication會再次藉助Spring-FactoriesLoader,查找並加載classpath中所有可用的ApplicationContext-Initializer,然後遍歷調用這些ApplicationContextInitializer的initialize(applicationContext)方法來對已經創建好的ApplicationContext進行進一步的處理。

8) 遍歷調用所有SpringApplicationRunListener的contextPrepared()方法。

9) 最核心的一步,將之前通過@EnableAutoConfiguration獲取的所有配置以及其他形式的IoC容器配置加載到已經準備完畢的ApplicationContext。

10) 遍歷調用所有SpringApplicationRunListener的contextLoaded()方法。

11) 調用ApplicationContext的refresh()方法,完成IoC容器可用的最後一道工序。

12) 查找當前ApplicationContext中是否註冊有CommandLineRunner,如果有,則遍歷執行它們。

13) 正常情況下,遍歷執行SpringApplicationRunListener的finished()方法、(如果整個過程出現異常,則依然調用所有SpringApplicationRunListener的finished()方法,只不過這種情況下會將異常信息一併傳入處理)
去除事件通知點後,整個流程如下:

在這裏插入圖片描述

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