1. 环境搭建
代码已经上传至 https://github.com/masteryourself-tutorial/tutorial-spring ,详见
tutorial-spring-boot-core/tutorial-spring-boot-helloworld
工程
1.1 配置文件
1. pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 可以将应用打包成一个可执行的jar包 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.4.RELEASE</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
1.2 代码
1. HelloWorldApplication
@SpringBootApplication
public class HelloWorldApplication {
public static void main(String[] args) {
SpringApplication.run(HelloWorldApplication.class, args);
}
}
2. HelloWorldController
@RestController
public class HelloWorldController {
@ResponseBody
@RequestMapping("/hello")
public String hello() {
return "Hello World!";
}
}
2. 原理分析
2.1 pom.xml 解析
2.1.1 spring-boot-dependencies 依赖分析
- 项目中引入
spring-boot-dependencies
jar 包,这个 jar 包管理了 Spring 用到的所有第三方组件的依赖,因此在 Spring Boot 工程中,只要是被 Spring 管理的组件,都不需要编写版本号
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
- 如以下版本号均被管理,更多内容可参考
spring-boot-dependencies
包
<properties>
<activemq.version>5.15.9</activemq.version>
<antlr2.version>2.7.7</antlr2.version>
<appengine-sdk.version>1.9.73</appengine-sdk.version>
<artemis.version>2.6.4</artemis.version>
<aspectj.version>1.9.2</aspectj.version>
<assertj.version>3.11.1</assertj.version>
...
</properties>
2.1.2 spring-boot-starter-web jar 包分析
spring-boot-starter-web
这个 jar 包依赖了 Spring 运行时期的所有 jar 包信息,而且引入了tomcat-embed-core
jar 包,将 tomcat 内置了,所以可以直接通过main
方法启动 web 容器
2.2 入口类分析
2.2.1 @SpringBootApplication 注解分析
-
@SpringBootApplication 标注在某个类上就说明这个类是 SpringBoot 的主配置类,它会运该类的 main 方法来启动 SpringBoot 应用
-
这个注解是复合注解,其中包括了如下注解,下面我们详细解释每个注解的作用
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM,
classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
1. @SpringBootConfiguration
- 表示是一个 SpringBoot 的配置类,作用同
@Configuration
,相当于是 Spring 的一个配置文件
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
2. @EnableAutoConfiguration
- 开启自动配置功能,这个注解也是个复合注解,它向容器中导入了
AutoConfigurationImportSelector
bean
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
-
AutoConfigurationImportSelector
实现了DeferredImportSelector
,所以这里会延时导入,之前版本没有实现这个接口,那么就会调用selectImports
方法,实现了就会调用AutoConfigurationGroup#process
方法 -
这个方法中有非常重要的一步:
getAutoConfigurationMetadata()
,即获取自动配置类的描述信息,它会读取META-INF/spring.factories
这个文件中org.springframework.boot.autoconfigure.EnableAutoConfiguration
对应的值,即所有的自动配置类 -
读取配置类的代码
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
Assert.notEmpty(configurations,
"No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
META-INF/spring.factories
中的部分配置内容如下,在spring-boot-autoconfigure-xxx.RELEASE.jar
包下
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.CloudServiceConnectorsAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
...
@AutoConfigurationPackage
的作用是向容器中导入了AutoConfigurationPackages.Registrar
bean,即自动扫包,它会将主配置类(@SpringBootApplication
标注的类)的所在包及下面所有子包里面的所有组件扫描到 Spring 容器中
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
3. ComponentScan
-
添加自定义的扫包规则
-
主要是排除两个过滤器:
TypeExcludeFilter
和AutoConfigurationExcludeFilter