public class SpringApplication { public SpringApplication(Class... primarySources) { this((ResourceLoader)null, primarySources); } public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) { this.sources = new LinkedHashSet(); this.bannerMode = Mode.CONSOLE; this.logStartupInfo = true; this.addCommandLineProperties = true; this.addConversionService = true; this.headless = true; this.registerShutdownHook = true; this.additionalProfiles = new HashSet(); this.isCustomEnvironment = false; this.resourceLoader = resourceLoader; Assert.notNull(primarySources, "PrimarySources must not be null"); // 保存主配置類 this.primarySources = new LinkedHashSet(Arrays.asList(primarySources)); // 判斷當前是否一個web應用 this.webApplicationType = WebApplicationType.deduceFromClasspath(); // 從類路徑下找到META-INF/spring.factories配置的全部ApplicationContextInitializer;而後保存起來。 this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class)); // 從類路徑下找到META-INF/spring.factories配置的全部ApplicationListener this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class)); //從多個配置類中找到有main方法的主配置類 this.mainApplicationClass = this.deduceMainApplicationClass(); }
public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList(); this.configureHeadlessProperty(); // 獲取SpringApplicationRunListener; 從類路徑下META-INF/spring.factories獲取 SpringApplicationRunListeners listeners = this.getRunListeners(args); // 回調全部的獲取SpringApplicationRunListener.starting()方法 listeners.starting(); Collection exceptionReporters; try { // 封裝命令行參數 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); // 準備環境 ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments); this.configureIgnoreBeanInfo(environment); // 建立環境完成後回調SpringApplicationRunListener.environmentPrepared();表示環境準備完成 Banner printedBanner = this.printBanner(environment); // 建立ApplicationContext;決定建立web的IOC仍是普通的IOC context = this.createApplicationContext(); exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context); // 準備上下文環境;將environment保存到IOC中,並且applyInitializers(); // 並且applyInitializers():回調以前保存的全部ApplicationContextInitializer的initialize方法 // 回調全部的SpringApplicationRunListener的contextPrepared(); this.prepareContext(context, environment, listeners, applicationArguments, printedBanner); // prepareContext運行完成之後回調全部的SpringApplicationRunListener的contextLoaded(); // 掃描容器;IOC容器初始化(若是是web應用還會建立嵌入的Tomcat); // 掃描,建立,加載全部組件的地方(配置類,組件,自動配置) this.refreshContext(context); // 從IOC容器中獲取全部的ApplicationRunner和CommandLineRunner進行回調 // ApplicationRunner先回調,CommandLineRunner再回調 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); // 整個SpringBoot應用啓動完成之後返回啓動的IOC容器 return context; } catch (Throwable var9) { this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null); throw new IllegalStateException(var9); } }
public class CustomApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { @Override public void initialize(ConfigurableApplicationContext configurableApplicationContext) { System.out.println("ApplicationContextInitializer.....initialize"); } }
SpringApplicationRunListenerjava
public class CustomSrpingApplicationRunListener implements SpringApplicationRunListener { // 必須有的構造器 public CustomSrpingApplicationRunListener(SpringApplication application,String[] args){ } @Override public void starting() { System.out.println("SpringApplicationRunListener...starting...."); } @Override public void environmentPrepared(ConfigurableEnvironment environment) { Object o = environment.getSystemEnvironment().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..started"); } @Override public void running(ConfigurableApplicationContext context) { System.out.println("SpringApplicationRunListener..running"); } @Override public void failed(ConfigurableApplicationContext context, Throwable exception) { System.out.println("SpringApplicationRunListener..failed"); } }
配置(META-INF/spring.factories)web
org.springframework.context.ApplicationContextInitializer=com.desperado.demo.CustomApplicationContextInitializer org.springframework.boot.SpringApplicationRunListener=com.desperado.demo.CustomSrpingApplicationRunListener
只須要放在IOC容器中的監聽器。
ApplicationRunnerspring
@Component public class CustomApplicationRunner implements ApplicationRunner { @Override public void run(ApplicationArguments args) { System.out.println("ApplicationRunner ... run...."); } }
CommandLineRunnerapache
@Component public class CustomCommandLineRunner implements CommandLineRunner { @Override public void run(String... args) { System.out.println("commandLineRunner ... run ..."); } }
要使用到的註解
@Configuration 指定類是一個配置類
@ConditionalOnXXX 在指定條件成立的狀況下自動配置生效、
@AutoConfigureAfter 在特定自動裝配class以後(指定自動配置類的順序)
@AutoConfigureBefore 在特定自動裝配class以前(指定自動配置類的順序)
@AutoConfigureOrder 指定順序
@Bean 給容器中添加組件
@ConfigurationPropertie 結合相關xxxProperties類來綁定相關的配置。
@EnableConfigurationProperties 讓xxxProperties生效加入到容器中。app
加載方式
自動配置類要能加載,將須要啓動就加載的自動配置類,配置在META-INF/spring.factories文件中。less
啓動器模式
啓動器只用來作依賴導入,專門寫一個自動配置模塊。啓動器依賴自動配置,使用時只須要引入啓動器(starter)。maven
啓動器規則
啓動器就是個空jar文件,僅提供輔助性依賴管理,這些依賴可能用於自動裝配或者其餘庫。ide
命名規範:
- 推薦使用如下命名規範
- 官方命名空間
- 前綴:spring-boot-starter-
- 模式:spring-boot-starter-模塊名
- 自定義命名空間
- 後綴:-spring-boot-starter
- 模式:模塊名-spring-boot-starterspring-boot
<?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.desperado.starter</groupId> <artifactId>desperado-spring-boot-starter</artifactId> <version>0.0.1-SNAPSHOT</version> <!-- 啓動器 --> <dependencies> <!-- 引入自動配置模塊 --> <dependency> <groupId>com.desperado.starter</groupId> <artifactId>desperado-spring-boot-starter-autoconfigurer</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies> </project>
2). 自動配置模塊ui
<?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.desperado.starter</groupId> <artifactId>desperado-spring-boot-starter-autoconfigurer</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.5.RELEASE</version> <relativePath/> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <!-- 引入spring-boot-starter;全部starter的基本配置 --> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> </dependencies> </project>
3). 編寫配置文件類
@ConfigurationProperties(prefix = "desperado.custom") public class CustomProperties { 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; } }
4). 進行配置文件的處理
public class CustomService { CustomProperties customProperties; public CustomProperties getCustomProperties(){ return customProperties; } public void setCustomProperties(CustomProperties customProperties){ this.customProperties = customProperties; } public String sayHello(String name){ return customProperties.getPrefix()+"-"+name+customProperties.getSuffix(); } }
5). 編寫自動配置類
@ConditionalOnWebApplication @EnableConfigurationProperties(CustomProperties.class) public class CustomServiceAutoConfiguration { @Autowired CustomProperties customProperties; @Bean public CustomService customService(){ CustomService customService = new CustomService(); customService.setCustomProperties(customProperties); return customService; } }