springBoot 启动配置原理
- springBoot 几个重要的事件回调机制
- 配置在 META_INF/spring.factories
- ApplicationContextInitializer
- SpringApplicationRunListener
- 只需要放在 ioc 容器中
- ApplicationRunner
- CommanLineRunner
启动流程:
一、 创建 SpringApplication 对象(1.x 版本)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| initialize(sources); private void initialize(Object[] sources) { if (sources != null && sources.length > 0) { this.sources.addAll(Arrays.asList(sources)); } this.webEnvironment = deduceWebEnvironment(); setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = deduceMainApplicationClass(); }
|
二、 运行 run 方法(1.x 和 2.x)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList(); this.configureHeadlessProperty();
SpringApplicationRunListeners listeners = this.getRunListeners(args); listeners.starting();
Collection exceptionReporters; try { ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments); this.configureIgnoreBeanInfo(environment); Banner printedBanner = this.printBanner(environment);
context = this.createApplicationContext(); exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context); this.prepareContext(context, environment, listeners, applicationArguments, printedBanner); this.refreshContext(context); this.afterRefresh(context, applicationArguments); stopWatch.stop(); if (this.logStartupInfo) { (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch); } listeners.started(context); this.callRunners(context, applicationArguments); } catch (Throwable var10) { this.handleRunFailure(context, var10, exceptionReporters, listeners); throw new IllegalStateException(var10); }
try { listeners.running(context); return context; } catch (Throwable var9) { this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null); throw new IllegalStateException(var9); } }
|
三、事件监听机制
配置在 META-INF/spring.factories
ApplicationContextInitalizer
1 2 3 4 5 6 7
| public class HelloApplicationContextInitializer implements ApplicationContextInitializer {
@Override public void initialize(ConfigurableApplicationContext configurableApplicationContext) { System.out.println("ApplicationContextInitializer...initialize..."+configurableApplicationContext); } }
|
SpringApplicationRunListener
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| public class HelloSpringApplicationRunListener implements SpringApplicationRunListener {
public HelloSpringApplicationRunListener(SpringApplication application, String[] args){
}
@Override public void environmentPrepared(ConfigurableEnvironment environment) { Object o = environment.getSystemProperties().get("os.name"); System.out.println("SpringApplicationRunListener...environmentPrepared.."+o); }
@Override public void contextPrepared(ConfigurableApplicationContext context) { System.out.println("SpringApplicationRunListener...contextPrepared..."); }
@Override public void contextLoaded(ConfigurableApplicationContext context) { System.out.println("SpringApplicationRunListener...contextLoaded..."); }
@Override public void started(ConfigurableApplicationContext context) { System.out.println("SpringApplicationRunListener...starting..."); }
@Override public void failed(ConfigurableApplicationContext context, Throwable exception) { System.out.println("SpringApplicationRunListener...finished..."); } }
|
配置(META-INFO/spring.factories)
1 2 3 4 5
| org.springframework.context.ApplicationContextInitializer=\ com.oy.springboot.listener.HelloApplicationContextInitializer
org.springframework.boot.SpringApplicationRunListener=\ com.oy.springboot.listener.HelloSpringApplicationRunListener
|
只需要放在 ioc 容器中
ApplicationRunner
1 2 3 4 5 6 7
| @Component public class HelloApplicationRunner implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { System.out.println("ApplicationRunner...run...."); } }
|
CommandLineRunner
1 2 3 4 5 6 7
| @Component public class HelloCommandLineRunner implements CommandLineRunner { @Override public void run(String... args) throws Exception { System.out.println("CommandLineRunner...run..."+ Arrays.asList(args)); } }
|
测试:
自定义 starter
starter:
1.编写自动配置
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Configuration @ConditionalOnXXX @AutoConfigureAfter @Bean
@ConfigurationPropertie @EnableConfigurationProperties
自动配置类要能加载 将需要启动就能加载的自动配置类,配置在META-INF/spring.factories org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
|
- 模式:
演示步骤(参考):
- 项目结构
先创建一个空项目,然后 oy-spring-boot-starter(用 maven 创建)和 oy-spring-boot-starter-autoconfigurer(spring Initializr 创建)
【oy-spring-boot-starter】 pom.xml 配置
1 2 3 4 5 6
| <dependencies> <dependency> <groupId>com.oy.starter</groupId> <artifactId>oy-spring-boot-starter-autoconfigurer</artifactId> <version>0.0.1-SNAPSHOT</version> </dependencies>
|
【oy-spring-boot-starter-autoconfigurer】 pom.xml 配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <?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 https://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>2.3.3.RELEASE</version> <relativePath/> </parent> <groupId>com.oy.starter</groupId> <artifactId>oy-spring-boot-starter-autoconfigurer</artifactId> <version>0.0.1-SNAPSHOT</version> <name>oy-spring-boot-starter-autoconfigurer</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</artifactId> </dependency> </dependencies>
</project>
|
【HelloProperties】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @ConfigurationProperties(prefix = "oy.hello") public class HelloProperties { private String prefix; private String suffix;
public String getPrefix() { return prefix; }
public void setPrefix(String prefix) { this.prefix = prefix; }
public String getSuffix() { return suffix; }
public void setSuffix(String suffix) { this.suffix = suffix; } }
|
【HelloService】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class HelloService {
HelloProperties helloProperties;
public HelloProperties getHelloProperties() { return helloProperties; }
public void setHelloProperties(HelloProperties helloProperties) { this.helloProperties = helloProperties; }
public String sayHellAtguigu(String name){ return helloProperties.getPrefix()+"-" +name + helloProperties.getSuffix(); }
|
【HelloServiceAutoConfiguration】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Configuration @ConditionalOnWebApplication @EnableConfigurationProperties(HelloProperties.class) public class HelloServiceAutoConfiguration {
@Autowired HelloProperties helloProperties;
@Bean public HelloService helloService(){ HelloService service = new HelloService(); service.setHelloProperties(helloProperties); return service; } }
|
【spring.factories】
1 2
| org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.oy.starter.HelloServiceAutoConfiguration
|
测试:
- **spring-boot-08-starter-test **项目结构
【pom.xml】
1 2 3 4 5
| <dependency> <groupId>com.oy.stater</groupId> <artifactId>oy-spring-boot-starter</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
|
【HelloController.java】
1 2 3 4 5 6 7 8 9 10 11
| @RestController public class HelloController {
@Autowired HelloService helloService;
@GetMapping("/hello") public String hello(){ return helloService.sayHellAtguigu("haha"); } }
|