开始
- spring initilizer:根据依赖构建工具、springboot 版本等生成 Java 工程。
- Spring Boot starter的介绍以及原理、手把手教你手写一个最简单的 Spring Boot Starter、SpringBoot starter 演进过程、实战编写 SpringBoot starter
- Starter 命名规则
Spring 官方定义的 Starter 通常命名遵循的格式为 spring-boot-starter-{name},例如 spring-boot-starter-data-mongodb。Spring 官方建议,非官方 Starter 命名应遵循 {name}-spring-boot-starter 的格式,例如,myjson-spring-boot-starter。- Starter 提供了以下功能
整合了模块需要的所有依赖,统一集合到 Starter 中。
提供了默认配置,并允许我们调整这些默认配置。
提供了自动配置类对模块内的 Bean 进行自动装配,注入 Spring 容器中。- SpringBoot 项目启动时,类加载器会从 META-INF/spring.factories 加载给定类型的工厂实现的完全限定类名。也就是说类加载器得到工程中所有 jar 包中的 META-INF/spring.factories 文件资源,从而得到了一些包括自动配置相关的类的集合,然后将它们实例化,放入 Spring 容器中。
在使用 spring boot 搭建项目时,只需要引入相应的 starter 坐标,免去了引入相关的依赖以及设置初始化的配置等繁琐操作。
源码分析
入口程序
@SpringBootApplication
public class SpringDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringDemoApplication.class, args);
}
}
SpringApplication.run 根据入参 SpringDemoApplication 找到当前 SpringBoot 应用的配置类(即标注了 @SpringBootApplication 的类)
自动装配如何实现
todo:注解上的注解 Spring 或 Java 是怎么解析的?
从 @SpringBootApplication 入手
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
//...}
其中 @EnableAutoConfiguration 的实现 AutoConfigurationImportSelector,会从 /META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 配置文件下读取自动装配的配置类
// From org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getCandidateConfigurations
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = new ArrayList<>(
SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()));
// 从 /META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 配置文件中读取自动装配的类
ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add);
Assert.notEmpty(configurations,
"No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
// From org.springframework.boot.context.annotation.ImportCandidates#load
private static final String LOCATION = "META-INF/spring/%s.imports";
public static ImportCandidates load(Class<?> annotation, ClassLoader classLoader) {
Assert.notNull(annotation, "'annotation' must not be null");
ClassLoader classLoaderToUse = decideClassloader(classLoader);
String location = String.format(LOCATION, annotation.getName());
Enumeration<URL> urls = findUrlsInClasspath(classLoaderToUse, location);
List<String> importCandidates = new ArrayList<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
importCandidates.addAll(readCandidateConfigurations(url));
}
return new ImportCandidates(importCandidates);
}
从自动装配类主要有:
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
org.springframework.boot.autoconfigure.netty.NettyAutoConfiguration
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
// 启动 Servlet 容器
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration
// SpringMVC 相关配置
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
SpringBoot 启动过程
ServletWebServerApplicationContext 是 SpringBoot 「Web应用」对应的容器,其重写了 onRefresh(), 在 Spring 刷新容器时,会回调该方法。
ServletWebServerApplicationContext#onRresh() :
@Override
protected void onRefresh() {
super.onRefresh();
try {
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create");
ServletWebServerFactory factory = getWebServerFactory();
createWebServer.tag("factory", factory.getClass()