Spring Boot 部署与自动装配

本文最后更新于 2025年7月13日 中午

Start Up

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@RestController
@RequestMapping("/Hello")
public class HelloController{
@RequestMapping("/world")
public String Hello(){
return "hello world";
}
}

@SpringBootApplication
public class SpringwebApplication{
public static void main(String[] args){
SpringApplication app = new SpringApplication(SpringwebApplication.class);
app.run(args);
}
}

Spring Boot 会从application.properties 中加载配置

配置加载顺序

1
2
3
4
5
6
1. 根目录   application.propertites
2. 根目录的config文件 .\\config\\application.propertites
3. 项目根目录 root\\application.propertites
4. 项目根目录的config文件 root\\config\\application.propertites
5. 直接使用 --spring.config.location = path 作为输入参数 class path 查询
6. 直接传入物理配置路径

环境配置

通过spring.profiles.active = prod(则会加载一个application-prod文件)

1
2
application-dev.propertites 
application-prod.propertites

批量注入属性

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
application.properties :
user.name = codfish
user.age = 18

//User类:
@Component
@ConfigurationProperties(prefix="user")
public class User {
private String username ;
private Integer age ;
public String getUsername(){
return username ;
}
public void setUsername(String username){
this.username = username;
}
public Integer getAge(){
return age ;
}
public void setAge(Integer age){
this.age = age ;
}
}

// 测试类:
@SpringBootTest
class SpringwebApplicationTests {
@Autowired
private User user ;

@Test
void contextLoads() {
System.out.println( user);
}

}

// 输出 User{username="codfish",age=18}

添加属性自动提示

添加 spring-boot-configuration-processor 依赖

使能注解处理器(idea)

属性注入的两种方式

properties

1
2
3
4
5
6
7
8
9
server.port=8083
user.username = codfish
user.age = 8
user.birthday = 2019/05/01
user.hobbies= [a,v,c]
user.girlfriend.3=cat //字典或自定义类需要使用.key 来进行赋值
user.girlfriend.8=li
user.address.id=3
user.address.desc=cheng hua avenue

yml

1
2
3
4
5
6
7
8
9
10
11
12
User:
username: codfish
age: 18
hobbies: # 列表支持 数组赋值或 yaml 格式赋值
- 1
- 2
- 3
girl-friend: # 字典支持 {key:value,key:value} 或 yaml格式赋值
1: zhao
2: li
address: {id: 1, desc: zhongguancun}
birthday: 2020/08/06

可以使用 ${} 在配置文件中进行占位

1
2
3
4
5
6
7
8
9
${random.value}
${random.int}
${random.int[1024,65536]} 范围
${random.int(2)} 范围

@Validated 进行数据校验

不能为空的值 指定为NOT NULL

Spring Boot自动装配过程

SpringBootApplication

从主程序开始

1
2
3
4
5
6
7
@SpringBootApplication
class SpringBootwebApplication{
public static void main(String[] args){
SpringApplication app = new SpringApplication(SpringBootwebApplication.class);
app.run(args);
}
}

@SpringBootApplication 是一个合成注解

其中包含了 一些元注解

@Target({ElementType.TYPE}) //元注解 定义注解使用的位置,这里声明了可以在类位置进行注解
@Retention(RetentionPolicy.RUNTIME) // 元注解:指定注解的生命周期。RetentionPolicy.RUNTIME 表示注解在运行时仍然可用,JVM 会保留它,可通过反射读取。
@Documented // 元注解:表示该注解会被包含在 Javadoc 文档中。
@Inherited // 元注解:表示子类可以继承父类上标注的注解(仅限 class 类型注解,对方法和字段无效)。

Spring 提供的注解

@SpringBootConfiguration // @Configuration 的派生注解,标识该类是 Spring Boot 应用的配置类入口。
@EnableAutoConfiguration // 启用 Spring Boot 的自动配置机制,根据类路径中的依赖及配置自动装配 Spring Bean。
@ComponentScan(

// 扫描指定包路径下的组件(如 @Component、@Service、@Controller 等),
// excludeFilters 用于排除指定类型的类(如自动配置类、用户配置类),防止重复装配或冲突。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Target({ElementType.TYPE})  
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
...
}

通过 EnableAutoConfiguration 自动装配支持自动装配的配置类

通过 ComponentScan 加载剔除了用户配置类和自动装配类的其他类。

EnableAutoConfiguration

EnableAutoConfiguration 注解中提供了两个注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Target({ElementType.TYPE})              // 注解位置
@Retention(RetentionPolicy.RUNTIME) // 生命周期
@Documented
@Inherited
@AutoConfigurationPackage // 提供工具方法
@Import({AutoConfigurationImportSelector.class}) // 执行自动装配的核心类
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

Class<?>[] exclude() default {};

String[] excludeName() default {};
}

AutoConfigurationPackage

autoConfigurationPackage 是一个声明为抽象类的静态工具类。它主要负责对基础java类路径的检索,并且提供方法将factories中的类描述信息注册到Beandefinition中。

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
public abstract class AutoConfigurationPackages {
private static final Log logger = LogFactory.getLog(AutoConfigurationPackages.class);
private static final String BEAN = AutoConfigurationPackages.class.getName();

public static boolean has(BeanFactory beanFactory) {

}
public static List<String> get(BeanFactory beanFactory) {

}
static final class BasePackages {
...
List<String> get() {
if (!this.loggedBasePackageInfo) {
if (this.packages.isEmpty()) {
if (AutoConfigurationPackages.logger.isWarnEnabled()) {
AutoConfigurationPackages.logger.warn("@EnableAutoConfiguration was declared on a class in the default package. Automatic @Repository and @Entity scanning is not enabled.");
}
} else if (AutoConfigurationPackages.logger.isDebugEnabled()) {
String packageNames = StringUtils.collectionToCommaDelimitedString(this.packages);
AutoConfigurationPackages.logger.debug("@EnableAutoConfiguration was declared on a class in the package '" + packageNames + "'. Automatic @Repository and @Entity scanning is enabled.");
}

this.loggedBasePackageInfo = true;
}

return this.packages;
}
}
}

AutoConfigurationImportSelector

autoconfigurationimportselector 是用于执行自动装配的核心类,它实现了一个延迟注册方法。

保证了整体的 Bean注入装配过程

1
2
3
4
5
6
7
8
9
@SpringBootApplication

@ComponentScan 扫描用户自定义类

@EnableAutoConfiguration 加载自动配置类

注册 BeanDefinition(用户 + 自动配置类)

创建 Bean(实例化 → 注入依赖 → 初始化)
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
public class AutoConfigurationImportSelector implements DeferredImportSelector ... {
public Class<? extends DeferredImportSelector.Group> getImportGroup() {
return AutoConfigurationGroup.class;
// 回调传输存储了自动配置类信息集合的结构
}

private static final class AutoConfigurationGroup implements DeferredImportSelector.Group{
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector)

// 实现DeferredImportSelector的内部接口Group。 用于存储通过检查的配置类
}
} // 外部的importselector 方法基本已被弃用(存在是为了保持向前兼容)

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY; // 这一步完成了 对是否启用 @EnableAutoConfiguration 的判断
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
configurations = this.<String>removeDuplicates(configurations);
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = this.getConfigurationClassFilter().filter(configurations); // 条件注解匹配筛选
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
}

SpringBoot 的自动装配过程

对于常规配置类,直接进行Bean注册过程;

对于自动配置类先进行延迟处理;

待所有常规配置类注册完毕后,进行自动配置类的注册。之后进行Bean 的创建

Spring3 之后 使用类似org.springframework.boot.autoconfigure.AutoConfiguration.import 通过spi的方式 进行类的查询和加载

自动配置类加载

1
2
3
4
5
6
@Configuration(proxyBeanMethod=false) (允许类对bean进行代理)
@EnableConfigurationProperties(ServerPropertites.class ) // 声明启动了哪些属性
@ConditionalOnWebApplication(type= ConditionalOnWebApplication.Type.SERVLET) // 环境未SERVLET
@ConditionalOnClass(CharacterEncodingFilter.class) // 类路径中存在对应类
@ConditionalOnProperty(prefix="server.servlet.encoding",value="enable",matchIfMissing=True) // server.servlet.encoding = true
条件满足时 加载组件

Spring Boot 部署与自动装配
http://gadoid.io/2025/06/30/Spring-Boot-部署与自动装配/
作者
Codfish
发布于
2025年6月30日
许可协议