直接從 SpringBoot 程序入口的 run 方法看起:java
1 public static ConfigurableApplicationContext run(Object source, String... args) { 2 return run(new Object[] { source }, args); 3 }
執行第 2 行的 run(new Object[] { source }, args) 方法:react
1 public static ConfigurableApplicationContext run(Object[] sources, String[] args) { 2 return new SpringApplication(sources).run(args); 3 }
能夠看到,這裏啓動其實是分爲兩步,先是建立 SpringApplication 對象,而後執行該對象的 run 方法。下面根據這兩步進行深刻:web
下一步會進入 SpringApplication 類的構造方法:redis
1 public SpringApplication(Object... sources) { 2 initialize(sources); 3 }
接着進入 initialize 方法:spring
1 private void initialize(Object[] sources) { 2 if (sources != null && sources.length > 0) { 3 // 保存配置類,包含入口類 4 this.sources.addAll(Arrays.asList(sources)); 5 } 6 // 判斷當前是不是一個 web 應用 7 this.webEnvironment = deduceWebEnvironment(); 8 // 從類路徑下找到 META-INF/spring.factories 配置的全部 ApplicationContextInitializer 類並反射建立實例並保存到當前 SpringApplication 實例的 initializers 屬性 9 setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); 10 // 從類路徑下找到 META-INF/spring.factories 配置的全部 ApplicationListener 類並反射建立實例保存到當前 SpringApplication 實例的 listeners 屬性 11 setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); 12 // 從調用棧中獲取到執行了 main 方法的配置類即入口類保存到當前 SpringApplication 實例的 mainApplicationClass 屬性 13 this.mainApplicationClass = deduceMainApplicationClass(); 14 }
在建立 SpringApplication 對象的過程當中實例化了類路徑下 META-INF/spring.factories 中 ApplicationContextInitializer 節對應的應用上下文初始化器類和 ApplicationListener 節對應的應用監聽器類並保存到了 SpringApplication 對象中。apache
能夠看到在不少包中都有這個文件,下面爲自動配置包中的 spring.factories 文件:springboot
# Initializers org.springframework.context.ApplicationContextInitializer=\ org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\ org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer # Application Listeners org.springframework.context.ApplicationListener=\ org.springframework.boot.autoconfigure.BackgroundPreinitializer # Auto Configuration Import Listeners org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\ org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener # Auto Configuration Import Filters org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\ org.springframework.boot.autoconfigure.condition.OnClassCondition # 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.CassandraRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\ 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.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.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.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.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.flyway.FlywayAutoConfiguration,\ org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\ org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\ org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\ 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.mobile.DeviceResolverAutoConfiguration,\ org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\ org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\ org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\ org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\ org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\ org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\ org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\ org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\ org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\ org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\ org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\ org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\ org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\ org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\ org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\ org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\ org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\ 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.DispatcherServletAutoConfiguration,\ org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\ org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\ org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\ org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\ org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\ org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,\ org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\ org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\ org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration # Failure analyzers org.springframework.boot.diagnostics.FailureAnalyzer=\ org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\ org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\ org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer # Template availability providers org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\ org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\ org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\ org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\ org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\ org.springframework.boot.autoconfigure.web.JspTemplateAvailabilityProvider
執行 org.springframework.boot.SpringApplication#run(java.lang.String...) 方法:websocket
public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); // 聲明一個 IoC 容器 ConfigurableApplicationContext context = null; FailureAnalyzers analyzers = null; // AWT 相關 configureHeadlessProperty(); // 經過 getSpringFactoriesInstances 從類路徑下找到 META-INF/spring.factories 配置的全部 SpringApplicationRunListener 類並反射建立實例返回 SpringApplicationRunListeners listeners = getRunListeners(args); // 回調執行全部 SpringApplicationRunListener 實例的 starting 方法 listeners.starting(); try { // 封裝命令行參數 ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); // 準備環境,建立環境完成後在該方法中又回調執行了全部 SpringApplicationRunListener 實例的 environmentPrepared 方法,表示環境準備完成 ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); // 控制檯打印 SpringBoot 圖標 Banner printedBanner = printBanner(environment); // 根據當前環境的不一樣建立不一樣類型的 IoC 容器 context = createApplicationContext(); // 初始化異常分析器 analyzers = new FailureAnalyzers(context); // 準備上下文環境: // 一、將 environment 保存到了 context 即 IoC 容器中 // 二、經過 applyInitializers(context) 方法,執行了全部 ApplicationContextInitializer 實例的 initialize(context) 方法(這些 ApplicationContextInitializer 實例是在初始化 SpringApplication 實例時建立保存的) // 三、還會回調執行全部 SpringApplicationRunListener 實例的 contextPrepared(context) 方法 // 四、在 prepareContext 方法最後一行還會回調執行全部 SpringApplicationRunListener 實例的 contextLoaded(context) 方法 prepareContext(context, environment, listeners, applicationArguments, printedBanner); // 刷新 IoC 容器,IoC 容器初始化,掃描、建立、加載全部組件(配置類、自動配置功能),若是是 web 應用,在這一步還會建立嵌入式 Servlet 容器 refreshContext(context); // 刷新後處理,會經過 callRunners(context, args) 方法從 IoC 容器中獲取全部 ApplicationRunner 和 CommandLineRunner 的 bean,並回調它們的 run 方法 afterRefresh(context, applicationArguments); // 回調執行全部的 SpringApplicationRunListener 實例的 finished 方法,表示應用啓動完成 listeners.finished(context, null); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } // 整個 SpringBoot 應用啓動完成後返回 IoC 容器 return context; } catch (Throwable ex) { handleRunFailure(context, listeners, analyzers, ex); throw new IllegalStateException(ex); } }
總結:session
在 SpringBoot 應用啓動的過程當中會回調一些咱們預配置組件的指定方法,這些組件能夠是咱們配置在指定文件中的類,也能夠是咱們註冊到 IoC 容器的 bean。分類以下:app
配置在 META-INF/spring.factories 中:
註冊在 IoC 容器中:
執行的方法按回調順序排序以下:
瞭解了 SpringBoot 程序的啓動流程後,咱們也能夠本身編寫一個 starter 了,下面爲一個小案例,功能是讓程序在啓動時註冊一個 hello 組件,而且能經過配置修改輸出內容。
一、使用 maven 建立一個 SpringBoot 程序做爲自動配置組件,依賴以下:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.19.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.zze.springboot</groupId> <artifactId>mystarter_autoconfigure</artifactId> <version>0.0.1-SNAPSHOT</version> <name>mystarter_autoconfigure</name> <description>Demo project for Spring Boot</description> <packaging>jar</packaging> <properties> <java.version>1.8</java.version> </properties> <dependencies> <!--引入 spring-boot-starter--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> </dependencies> </project>
二、編寫與配置文件屬性映射的配置類:
package com.zze.springboot.config; import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "com.zze") public class HelloProperties { private String name; private String remark; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } }
三、編寫 hello 服務:
package com.zze.springboot.service; import com.zze.springboot.config.HelloProperties; public class HelloService { private HelloProperties helloProperties; public void setHelloProperties(HelloProperties helloProperties) { this.helloProperties = helloProperties; } public void sayHello() { System.out.println("hello " + helloProperties.getName() + " " + helloProperties.getRemark()); } }
四、編寫自動配置類:
package com.zze.springboot.autoconfigure; import com.zze.springboot.config.HelloProperties; import com.zze.springboot.service.HelloService; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * 自定義自動配置類 */ @EnableConfigurationProperties(HelloProperties.class) // 啓用指定類的配置映射,並將配置類實例註冊到 IoC 容器 @Configuration @ConditionalOnWebApplication // web 應用時才生效 public class MyStarterAutoConfiguration { private HelloProperties helloProperties; public MyStarterAutoConfiguration(HelloProperties helloProperties){ this.helloProperties = helloProperties; } // 註冊 hello 服務到 IoC 容器 @Bean public HelloService helloService(){ HelloService helloService = new HelloService(); helloService.setHelloProperties(helloProperties); return helloService; } }
五、配置自動配置類,讓程序啓動時加載自動配置類讓其生效:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.zze.springboot.autoconfigure.MyStarterAutoConfiguration
一、建立普通的 maven 項目做爲 starter 組件,引入上面編寫的自動配置組件依賴:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zze.springboot</groupId> <artifactId>mystarter</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!--引入自動配置模塊--> <dependency> <groupId>com.zze.springboot</groupId> <artifactId>mystarter_autoconfigure</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies> </project>
二、將自動配置組件及 starter 組件安裝到 maven 倉庫。
一、使用 maven 新建立一個 SpringBoot 項目,引入咱們編寫的 starter 依賴:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.19.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.zze.springboot</groupId> <artifactId>mystarter</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
二、配置 hello 服務所須要的相關屬性:
com.zze.name=張三
com.zze.remark=會員
三、直接注入 hello 服務,測試:
package com.example.demo; import com.zze.springboot.service.HelloService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class DemoApplicationTests { @Autowired private HelloService helloService; @Test public void contextLoads() { helloService.sayHello(); /* hello 張三 會員 */ } }