配置原理解析
1. 启动配置原理
配置在META-INF/spring.factories中
ApplicationContextInitializer
SpringApplicationRunListener
添加到IoC容器中
AppllicationRunner
CommandLineRunner
1.1. 启动流程
1 2 3
   | SpringApplication.run(BootdataApplication.class, args);
  return new SpringApplication(primarySources).run(args);
   | 
 
1.1.1. 创建SpringApplication对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
   | public SpringApplication(Class<?>... primarySources) { 		this(null, primarySources); 	}
  public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { 		this.resourceLoader = resourceLoader; 		Assert.notNull(primarySources, "PrimarySources must not be null");      		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));      		this.webApplicationType = WebApplicationType.deduceFromClasspath();      		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));      		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));      		this.mainApplicationClass = deduceMainApplicationClass(); 	}
  | 
 
1.1.1.1. ApplicationContextInitializer
从类路径下找到META-INF/spring.factories配置的所有ApplicationContextInitializer



1.1.1.2. ApplicationListener

1.1.1.3. deduceMainApplicationClass
1 2 3 4 5 6 7 8 9 10 11 12 13 14
   | private Class<?> deduceMainApplicationClass() { 		try { 			StackTraceElement[] stackTrace = new RuntimeException().getStackTrace(); 			for (StackTraceElement stackTraceElement : stackTrace) { 				if ("main".equals(stackTraceElement.getMethodName())) { 					return Class.forName(stackTraceElement.getClassName()); 				} 			} 		} 		catch (ClassNotFoundException ex) { 			 		} 		return null; 	}   
  | 
 
1.1.2. 运行run方法
refreshContext(context);所有组件的加载
1.1.2.1. SpringApplicationRunListeners
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 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
   | public ConfigurableApplicationContext run(String... args) { 		StopWatch stopWatch = new StopWatch(); 		stopWatch.start(); 		ConfigurableApplicationContext context = null; 		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); 		configureHeadlessProperty();      		SpringApplicationRunListeners listeners = getRunListeners(args);     
 
 
 
 
 
 
  		listeners.starting(); 		try {        			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);              
 
 
 
  			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); 			configureIgnoreBeanInfo(environment);        			Banner printedBanner = printBanner(environment);       
 
 
 
 
 
 
 
 
 
 
 
 
 
  			context = createApplicationContext(); 			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, 					new Class[] { ConfigurableApplicationContext.class }, context);              
 
 
 
 
 
 
 
 
 
 
  			prepareContext(context, environment, listeners, applicationArguments, printedBanner);        			refreshContext(context);        			afterRefresh(context, applicationArguments); 			stopWatch.stop(); 			if (this.logStartupInfo) { 				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch); 			}        			listeners.started(context);       
 
 
 
  			callRunners(context, applicationArguments); 		} 		catch (Throwable ex) { 			handleRunFailure(context, ex, exceptionReporters, listeners); 			throw new IllegalStateException(ex); 		}
  		try { 			listeners.running(context); 		} 		catch (Throwable ex) { 			handleRunFailure(context, ex, exceptionReporters, null); 			throw new IllegalStateException(ex); 		} 		return context; 	}
  | 
 
       SpringApplicationRunListeners
       
2. 自定义starters
2.1. 自动配置
1 2 3 4 5 6 7 8 9 10 11 12 13
   |  @Configuration
  @ConditionalOnxxx
  @AutoConfigureAfter
  @Bean
 
  @ConfigurationProperties(prefix = "") 
  @EnableConfigurationProperties 
 
  | 
 
META-INF/spring.factories
1 2
   |  org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
 
  | 
 
2.2. 模式
启动器只用来做依赖导入
专门写一个自动配置模块
启动器依赖自动配置
xxx-spring-boot-starter
2.3. 创建项目
新建空项目
new Module:
Spring-Initalizer:hello-spring-boot-starter-autoconfigurer 
仅添加spring-boot-starter
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
   | <?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.2.0.RELEASE</version> 		<relativePath/>  	</parent> 	<groupId>com.runaccpeted</groupId> 	<artifactId>hello-spring-boot-starter-autoconfigurer</artifactId> 	<version>0.0.1-SNAPSHOT</version> 	<name>hello-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>
   | 
 
 
Maven:hello-spring-boot-starter
添加hello-spring-boot-starter-autoconfigurer依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
   | <?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.runaccpeted.starter</groupId>     <artifactId>hello-spring-boot-starter</artifactId>     <version>1.0-SNAPSHOT</version>
      <dependencies>                  <dependency>             <groupId>com.runaccpeted</groupId>             <artifactId>hello-spring-boot-starter-autoconfigurer</artifactId>             <version>0.0.1-SNAPSHOT</version>         </dependency>     </dependencies>
  </project>
   | 
 
HelloProperties
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
   | package com.runaccpeted.starter;
  import org.springframework.boot.context.properties.ConfigurationProperties;
  @ConfigurationProperties(prefix = "runaccpeted.hello") public class HelloProperties {
      private String name;
      public String getName() {         return name;     }
      public void setName(String name) {         this.name = name;     } }
 
   | 
 
HelloService
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   | package com.runaccpeted.starter;
  public class HelloService {
      HelloProperties helloProperties;
      public HelloService(HelloProperties helloProperties) {         this.helloProperties = helloProperties;     }
      public String saySomething(String name) {         return helloProperties.getName()+" "+name;     } }
 
   | 
 
HelloAutoConfiguration
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
   | package com.runaccpeted.starter;
  import org.springframework.beans.factory.annotation.Autowired; 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;
  @Configuration @ConditionalOnWebApplication @EnableConfigurationProperties(HelloProperties.class) public class HelloAutoConfiguration {     @Autowired     private HelloProperties helloProperties;
      public HelloProperties getHelloProperties() {         return helloProperties;     }
      public void setHelloProperties(HelloProperties helloProperties) {         this.helloProperties = helloProperties;     }
      @Bean     public HelloService helloService(){         HelloService service = new HelloService(helloProperties);         return service;     } }
   | 
 
2.5. spring.factories
1 2 3
   | # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.runaccpeted.starter.HelloAutoConfiguration  
   | 
 
2.6. 安装项目
无法安装 no test – 删除hello-spring-boot-starter-autoconfigurer 中的test文件夹

2.7. 运用到项目
1 2 3 4 5
   | <dependency>     <groupId>com.runaccpeted.starter</groupId>     <artifactId>hello-spring-boot-starter</artifactId>     <version>1.0-SNAPSHOT</version> </dependency>
   | 
 
TestController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   | package com.runaccpeted.controller;
  import com.runaccpeted.starter.HelloService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;
  @RestController public class TestController {     @Autowired     HelloService service;
      @RequestMapping("/starter")     public String test(){         return service.saySomething("Hello");     } }
   | 
 
application.properties
1
   | runaccpeted.hello.name=say:
   | 
 
