SpringBoot2基础详解

igxiaoshan Lv5

SpringBoot2入门

系统配置要求

  • JDK 8 +
  • Maven 3.3+
  • Idea 2019.+
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
## Maven配置
<mirrors>
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>

<profiles>
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
</profiles>

## 配置Maven厂库,JDK编译版本

Ddmo-HelloWorld

  • 引入依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
## pom文件
<groupId>org.igsshan</groupId>
<artifactId>springbootbasic</artifactId>
<version>1.0-SNAPSHOT</version>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>

<properties>
<java.version>8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
  • 主程序
1
2
3
4
5
6
7
// main主程序
@SpringBootApplication
public class HelloWorldApplication {
public static void main(String[] args) {
SpringApplication.run(HelloWorldApplication.class, args);
}
}
  • 业务层
1
2
3
4
5
6
7
8
9
// controller
@RestController
public class HelloWorldController {

@GetMapping("hello")
public String sayHelloWorld() {
return "hello SpringBoot2!";
}
}
  • 配置层
1
2
3
## application.yml
server:
port: 8080
  • 测试
1
2
3
4
5
6
7
// 启动main方法

// 请求路径
http://localhost:8080/hello

// 返回结果
hello SpringBoot2!
  • 简化部署
1
2
3
4
5
6
7
8
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

将项目打包成jar包,在服务器运行

jar -java path/hello.jar

1
2
3
4
5
6
## 服务启动
nohup java -jar `pwd`/app.jar &

## 服务停机
echo "current java pid is: `jps|grep app|awk -F ' ' '{print $1}'`"
kill -9 `jps|grep app|awk -F ' ' '{print $1}'`

注意 :

使用cmd命令springboot,会出现启动失败的情况

可以修改配置,取消方法: `右击cmd控制台窗口标题区区域打开[选项]取消勾选[快速编辑模式]

SpringBoot2自动配置

依赖管理

  • 项目父项目依赖管理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- 依赖管理 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>

<!-- 他的父项目 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.4.RELEASE</version>
</parent>

<!-- 几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制 -->
  • 父项目依赖控制
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
<?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>org.igsshan</groupId>
<artifactId>springbootbasicparent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>

<properties>
<java.version>8</java.version>
<maven.complier.source>1.8</maven.complier.source>
<meven.complier.targer>1.8</meven.complier.targer>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<!-- 版本仲裁 -->
<spring-boot-dependencies.version>2.3.4.RELEASE</spring-boot-dependencies.version>
</properties>

<dependencies>
</dependencies>

<dependencyManagement>
<dependencies>
<!-- 父工程管理 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot-dependencies.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

</project>
  • starter 场景启动器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--
1. spring-boot-starter-* ; *就是某种场景启动器
比如: spring-boot-starter-web 就是web场景启动器
2. 只要引入starter,这个场景所需要的所有依赖都会自动引入
-->
<!-- 所有场景启动器的底层依赖都是 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
  • 自动版本仲裁
1
2
3
4
1. 引入依赖默认都可以不写版本号
2. 引入非版本仲裁的jar,需要添加版本号

## 如果要使用非版本(默认)的版本,则需要在自己的pom文件中使用properties标签配合上述官方pom文件中的版本控制格式进行修改
  • 修改版本号
1
2
3
4
5
6
7
8
<!-- 
1、查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。
2、在当前项目里面重写配置
-->
<properties>
<mysql.version>5.1.43</mysql.version>
</properties>
<!-- 使用maven就近原则修改仲裁依赖版本号 -->

自动配置原理

自动配置

  • 自动配置tomcat

    • 引入tomcat依赖
    • 配置tomcat配置

    就可以完成tomcat的自动配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 主启动类
@SpringBootApplication
public class HelloWorldApplication {
public static void main(String[] args) {
SpringApplication.run(HelloWorldApplication.class, args);
}
}

/**
* 1. @SpringBootApplication: SpringBoot应用标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot就应该运行这个类的main方法来启动SpringBoot应用;
* 2. 主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来
* 3. 想要改变扫描路径,@SpringBootApplication(scanBasePackages="com.igsshan")
或者 @ComponentScan 指定扫描路径
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@SpringBootApplication 
// 相当于
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.igsshan.springbootbasic") // 默认包扫描到@SpringBootApplication注解主启动类层级

// 注意:
想要改变扫描路径,不能直接将@ComponentScan@SpringBootApplication一起使用,因为@SpringBootApplication 是由
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan组成的,
所以只能将 @SpringBootApplication 替换为
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan 这三个注解。
  • 解析@SpringBootApplication注解
1
2
3
4
5
// @SpringBootConfiguration 注解

@SpringBootConfiguration: 标注在某个类上,表示这是一个SpringBoot的配置类;
@Configuration: 配置类上标注这个注解;
配置类也是容器中的一个组件;
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
// @EnableAutoConfiguration 注解

@EnableAutoConfiguration: 开启自动配置
@EnableAutoConfiguration 告诉SpringBoot开启自动配置功能;

/**
* @EnableAutoConfiguration 注解解析
*/
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}

/**
* 解析 @AutoConfigurationPackage
* 1.1 自动配置包
* 2.1 Spring的底层注解@Import,给容器中导入一个组件;导入的组件由 AutoConfigurationPackages.Registrar.class 将主配置类(@SpringBootApplication标注的类)的所在包及下面所有子包里面的所有组件扫描到Spring容器;
*/
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {}

/**
* 解析 @Import(AutoConfigurationImportSelector.class)
* 1.1 给容器中导入组件
* 1.2 AutoConfigurationImportSelector 组件导入选择器
* 2.1 将所有需要导入的组件以全类名的方式返回;这些组件就会被添加到容器中;
* 2.2 会给容器中导入非常多的自动配置类(xxxAutoConfiguration);
* List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
*/

SpringBoot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效,帮我们进行自动配置工作

容器添加

组件添加
@Configuration
  • Full模式和Lite模式

    • full模式vslite模式详细说明

    • 使用

      • 配置类组件之间无依赖关系Lite模式,加速容器启动过程,减少判断
      • 配置类组件之间有依赖关系,方法会被调用得到之前单例组件,用Full模式
1
2
3
proxyBeanMethods: 代理bean的方法
1. Full(proxyBeanMethods = true),保证每个 @Bean 方法被调用多少次返回的组件都是单例的
2. Lite(proxyBeanMethods = false),每个 @Bean方法被调用多少次返回的组件都是新创建的
@Bean**,@Component,@Controller,@Service,**@Repository
1
2
3
4
5
6
7
根据它们的源码可以看到,
@Controller、@Service、@Repository 其本质就是Component。
它存在的本质只是给开发者看的,对Spring而言它们就都是Component。
@Controller 控制层类,
@Service 业务层类,
@Repository 持久层类,
@Component 无法归类到前3种时就称为组件。
@ComponentScan**,**@Import
1
2
注解说明:
@ComponentScan注解,主要是Spring IOC 容器在刷新的时候,会扫描对应包下标注了 @Component,@Configuration,@Controller,@Service,@Repository等注解的类,生成扫描到的类的Bean定义信息,最终都会保存到 BeanFactory 中的 BeanDefinitionMap 中

@ComponentScan注解原理

@Import给容器中自动创建出指定的类型的组件,默认组件的名字就是全类名

1
2
3
4
5
6
7
@Import({User.class, DBHelper.class})
@Configuration(proxyBeanMethods = false)
public class MyConfig {

}

// @Import注解自动从类中的 无参构造 创建一个实例注册到 IOC 容器中,容器中默认的id名为类的全限定名: user类就是 com.igsshan.bean.User
@Conditional

条件装配: 满足Contidional指定的条件,则进行条件注入

详细解释

原生Spring配置文件引入
@ImportResource

ImportResource注解用于导入Spring的配置文件

注意: 不使用@ImportResource注解,程序是不会对Spring的配置文件进行加载的

用法用例

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
// @ImportResource("classpath:beans.xml")
// 用来导入指定的配置文件 加在配置类上面


====================== spring xml 配置 =================
<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

<bean id="xiaohong" class="com.igsshan.springboootimportrersource.model.User">
<property name="name" value="zhangsan"></property>
<property name="age" value="18"></property>
</bean>

<bean id="jerry" class="com.igsshan.springboootimportrersource.model.Pet">
<property name="name" value="tomcat"></property>
</bean>
</beans>


====================== 配置类 =================
/**
* @author : igsshan
* @date : 2023/11/24 14:35
* @since : 1.0
*/
@ImportResource(value = {"classpath:base.xml"})
@Configuration
public class MyConfig {
}

====================== 启动类 =================
/**
* @author : igsshan
* @date : 2023/11/24 10:19
* @since : 1.0
*/
@SpringBootApplication
public class ImportResourceApplication {

public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(ImportResourceApplication.class, args);

System.out.println("======================测试=================");
boolean xiaohong = run.containsBean("xiaohong");
boolean jerry = run.containsBean("jerry");
System.out.println("xiaohong:" + xiaohong);
System.out.println("jerry:" + jerry);
}
}

测试结果

1
2
3
======================测试=================
xiaohong:true
jerry:true
配置绑定

使用Java Bean 对象读取到 properties/yml 文件中的内容

@ConfigurationProperties

@ConfigurationProperties+@Component注解实现读取配置注入容器

用法用例

1
2
3
4
5
### 配置文件
mycar:
enable: true
brand: 兰博基尼
price: 180000
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
===================== 配置类 ===================
/**
* @author : igsshan
* @date : 2023/11/24 15:02
* @since : 1.0
*/
@Component
@ConfigurationProperties(prefix = "mycar")
public class Car {

private boolean enable;
private String brand;
private Integer price;

public Car() {
}

public Car(String brand, Integer price) {
this.brand = brand;
this.price = price;
}

public String getBrand() {
return brand;
}

public void setBrand(String brand) {
this.brand = brand;
}

public Integer getPrice() {
return price;
}

public void setPrice(Integer price) {
this.price = price;
}

public boolean isEnable() {
return enable;
}

public void setEnable(boolean enable) {
this.enable = enable;
}

@Override
public String toString() {
return "Car{" +
"enable=" + enable +
", brand='" + brand + '\'' +
", price=" + price +
'}';
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
===================== 启动类 ===================
/**
* @author : igsshan
* @date : 2023/11/24 10:19
* @since : 1.0
*/
@SpringBootApplication
public class ImportResourceApplication {

public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(ImportResourceApplication.class, args);

System.out.println("======================测试=================");
Object car = run.getBean("car");
System.out.println(car);

}
}

测试结果

1
2
======================测试=================
Car{enable=true, brand='兰博基尼', price=180000}

@EnableConfigurationProperties+@ConfigurationProperties实现自动注入配置bean

@EnableConfigurationProperties作用是使ConfigurationProperties注解的类,装配配置信息并以标准的@Bean方式注入到IOC容器中

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
/**
* @author : igsshan
* @date : 2023/11/27 15:14
* @since : 1.0
*/
@Configuration
@ConfigurationProperties(prefix = "mybus")
public class Bus {

private boolean enable;
private String name;
private Integer age;

public Bus() {
}

public Bus(boolean enable, String name, Integer age) {
this.enable = enable;
this.name = name;
this.age = age;
}

public boolean isEnable() {
return enable;
}

public void setEnable(boolean enable) {
this.enable = enable;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}

@Override
public String toString() {
return "Tom{" +
"enable=" + enable +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
1
2
3
4
5
6
7
8
9
10
/**
* @author : igsshan
* @date : 2023/11/24 14:35
* @since : 1.0
*/
@ImportResource(value = {"classpath:base.xml"})
@Configuration
@EnableConfigurationProperties(value = {Bus.class})
public class MyConfig {
}

自动配置原理解析

引导加载配置类

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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/**
*
* @author Phillip Webb
* @author Stephane Nicoll
* @author Andy Wilkinson
* @since 1.2.0
*/
@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 {

/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {};

/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
@AliasFor(annotation = EnableAutoConfiguration.class)
String[] excludeName() default {};

/**
* Base packages to scan for annotated components. Use {@link #scanBasePackageClasses}
* for a type-safe alternative to String-based package names.
* <p>
* <strong>Note:</strong> this setting is an alias for
* {@link ComponentScan @ComponentScan} only. It has no effect on {@code @Entity}
* scanning or Spring Data {@link Repository} scanning. For those you should add
* {@link org.springframework.boot.autoconfigure.domain.EntityScan @EntityScan} and
* {@code @Enable...Repositories} annotations.
* @return base packages to scan
* @since 1.3.0
*/
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};

/**
* Type-safe alternative to {@link #scanBasePackages} for specifying the packages to
* scan for annotated components. The package of each class specified will be scanned.
* <p>
* Consider creating a special no-op marker class or interface in each package that
* serves no purpose other than being referenced by this attribute.
* <p>
* <strong>Note:</strong> this setting is an alias for
* {@link ComponentScan @ComponentScan} only. It has no effect on {@code @Entity}
* scanning or Spring Data {@link Repository} scanning. For those you should add
* {@link org.springframework.boot.autoconfigure.domain.EntityScan @EntityScan} and
* {@code @Enable...Repositories} annotations.
* @return base packages to scan
* @since 1.3.0
*/
@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};

/**
* The {@link BeanNameGenerator} class to be used for naming detected components
* within the Spring container.
* <p>
* The default value of the {@link BeanNameGenerator} interface itself indicates that
* the scanner used to process this {@code @SpringBootApplication} annotation should
* use its inherited bean name generator, e.g. the default
* {@link AnnotationBeanNameGenerator} or any custom instance supplied to the
* application context at bootstrap time.
* @return {@link BeanNameGenerator} to use
* @see SpringApplication#setBeanNameGenerator(BeanNameGenerator)
* @since 2.3.0
*/
@AliasFor(annotation = ComponentScan.class, attribute = "nameGenerator")
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

/**
* Specify whether {@link Bean @Bean} methods should get proxied in order to enforce
* bean lifecycle behavior, e.g. to return shared singleton bean instances even in
* case of direct {@code @Bean} method calls in user code. This feature requires
* method interception, implemented through a runtime-generated CGLIB subclass which
* comes with limitations such as the configuration class and its methods not being
* allowed to declare {@code final}.
* <p>
* The default is {@code true}, allowing for 'inter-bean references' within the
* configuration class as well as for external calls to this configuration's
* {@code @Bean} methods, e.g. from another configuration class. If this is not needed
* since each of this particular configuration's {@code @Bean} methods is
* self-contained and designed as a plain factory method for container use, switch
* this flag to {@code false} in order to avoid CGLIB subclass processing.
* <p>
* Turning off bean method interception effectively processes {@code @Bean} methods
* individually like when declared on non-{@code @Configuration} classes, a.k.a.
* "@Bean Lite Mode" (see {@link Bean @Bean's javadoc}). It is therefore behaviorally
* equivalent to removing the {@code @Configuration} stereotype.
* @since 2.2
* @return whether to proxy {@code @Bean} methods
*/
@AliasFor(annotation = Configuration.class)
boolean proxyBeanMethods() default true;

}
配置类分解

@SpringBootConfiguration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* Indicates that a class provides Spring Boot application
* {@link Configuration @Configuration}. Can be used as an alternative to the Spring's
* standard {@code @Configuration} annotation so that configuration can be found
* automatically (for example in tests).
* <p>
* Application should only ever include <em>one</em> {@code @SpringBootConfiguration} and
* most idiomatic Spring Boot applications will inherit it from
* {@code @SpringBootApplication}.
*
* @author Phillip Webb
* @author Andy Wilkinson
* @since 1.4.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {}

// @SpringBootConfiguration 是Spring标准 @Configuration 注释的替代方法。 两者之间的唯一区别是 @SpringBootConfiguration 允许自动找到配置。应用程序中只包含一个 @SpringBootConfiguration

ComponentScan

1
2
3
4
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

// 指定扫描哪些 spring 注解

@EnableAutoConfiguration

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
/**
* Enable auto-configuration of the Spring Application Context, attempting to guess and
* configure beans that you are likely to need. Auto-configuration classes are usually
* applied based on your classpath and what beans you have defined. For example, if you
* have {@code tomcat-embedded.jar} on your classpath you are likely to want a
* {@link TomcatServletWebServerFactory} (unless you have defined your own
* {@link ServletWebServerFactory} bean).
* <p>
* When using {@link SpringBootApplication @SpringBootApplication}, the auto-configuration
* of the context is automatically enabled and adding this annotation has therefore no
* additional effect.
* <p>
* Auto-configuration tries to be as intelligent as possible and will back-away as you
* define more of your own configuration. You can always manually {@link #exclude()} any
* configuration that you never want to apply (use {@link #excludeName()} if you don't
* have access to them). You can also exclude them via the
* {@code spring.autoconfigure.exclude} property. Auto-configuration is always applied
* after user-defined beans have been registered.
* <p>
* The package of the class that is annotated with {@code @EnableAutoConfiguration},
* usually via {@code @SpringBootApplication}, has specific significance and is often used
* as a 'default'. For example, it will be used when scanning for {@code @Entity} classes.
* It is generally recommended that you place {@code @EnableAutoConfiguration} (if you're
* not using {@code @SpringBootApplication}) in a root package so that all sub-packages
* and classes can be searched.
* <p>
* Auto-configuration classes are regular Spring {@link Configuration @Configuration}
* beans. They are located using the {@link SpringFactoriesLoader} mechanism (keyed
* against this class). Generally auto-configuration beans are
* {@link Conditional @Conditional} beans (most often using
* {@link ConditionalOnClass @ConditionalOnClass} and
* {@link ConditionalOnMissingBean @ConditionalOnMissingBean} annotations).
*
* @author Phillip Webb
* @author Stephane Nicoll
* @since 1.0.0
* @see ConditionalOnBean
* @see ConditionalOnMissingBean
* @see ConditionalOnClass
* @see AutoConfigureAfter
* @see SpringBootApplication
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}

// @AutoConfigurationPackage 指定了默认的报规则;将指定目录下的所有组件导入到IOC容器中,将扫描 路径注册到全局,给其他组件查询(例如 JPA)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* Registers packages with {@link AutoConfigurationPackages}. When no {@link #basePackages
* base packages} or {@link #basePackageClasses base package classes} are specified, the
* package of the annotated class is registered.
*
* @author Phillip Webb
* @since 1.3.0
* @see AutoConfigurationPackages
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {}

// 使用@import将AutoConfigurationPackages包下的Registrar类作为组件导入到容器中,然后使用Registrar中的方法批量完成组件的注册。
// 换而言之,指定了SpringBoot的管控范围;
1
2
3
4
5
6
7
8
9
@Import(AutoConfigurationImportSelector.class)

//AutoConfigurationImportSelector类中方法解析
1. 利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件
2. 调用List<String> configurations = getCandidateConfigurations(annotationMetadata,attributes),获取到所有需要导入到容器中的配置类
3. 利用工厂加载 Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader);得到所有组件
4. 从META-INF/spring.factories位置来加载一个文件
默认扫描当前系统里面所有 META-INF/spring.factories 位置的文件
spring-boot-antoconfigure-**.jar包里面也有 META-INF/spring.factories文件