SpringBoot(二)
目录
SpringBoot(二)
自动配置原理
pom.xml
- spring-boot-dependencies:核心依赖在父工程中
- 我们在引入一些Spring Boot不需要指定版本,就是因为有这些版本仓库
启动器
-
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> -
指定了Spring Boot的启动场景
-
比如spring-boot-starte-web就会自动导入web环境的所有依赖
-
Spring Boot会将所有的功能场景,都编程一个个的启动器
主程序:
-
注解:
@SpringBootApplication标注这个类是一个Spring Boot应用@SpringBootConfiguration:Spring Boot配置@Configuration:Spring配置类@Component:Spring组件
@EnableAutoConfiguration:自动配置@AutoConfigurationPackage:自动配置包@Import({Registrar.class}):自动配置包注册
@Import({AutoConfigurationImportSelector.class}):自动导入选择器List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);:获取所有配置
-
获取候选配置:
-
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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; }-
protected Class<?> getSpringFactoriesLoaderFactoryClass() { return EnableAutoConfiguration.class; }- 启动类下的所有资源被导入
-
META-INF/spring.factories:自动配置的核心文件- External Libraries -> Maven: org.springframework.boot:spring-boot-autoconfiguration -> META-INF -> spring.factories
-
loadFactoryNames:-
loadSpringFactories:-
URL url = (URL)urls.nextElement(); UrlResource resource = new UrlResource(url); Properties properties = PropertiesLoaderUtils.loadProperties(resource); -
所有资源加载到配置类中
-
-
-
-
-
@ConditionaOnXXX:核心注解,满足条件才生效- 因此需要导入对应的starter,自动配置才能生效
主启动类
SpringApplication的实例化
- 推断应用的类型是普通的项目还是Web项目
- 查找并加载所有可用初始化器,设置到initializers属性中
- 找出所有的应用程序监听器,设置到listeners属性中
- 推断并设置main方法的定义类,找到运行的主类
run方法的执行
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
ConfigurableApplicationContext context = null;
this.configureHeadlessProperty();
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
this.configureIgnoreBeanInfo(environment);
Banner printedBanner = this.printBanner(environment);
context = this.createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
this.refreshContext(context);
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, listeners);
throw new IllegalStateException(var10);
}
try {
listeners.running(context);
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}
YAML
配置文件
-
Spring Boot使用一个全局的配置文件,名字固定
- application.properties
- 语法结构:key=value
- application.yaml
- 语法结构:key:[空格]value
- application.properties
-
配置文件的作用:修改Spring Boot自动配置的默认值
简介
- YAML Ain't a Markup Language,YAML不是一种标记语言
- Yet Another Markup Language,仍是一种标记语言
语法
key: value
-
以此来表示一对键值对(空格不能省略)
-
以缩进来控制层级关系,只要是左边对齐的一列数据都是同一个层级的
-
属性的值和大小写都是敏感的
-
常用写法:
#普通key-value
name: yhr
##对象
student1:
name: yhr
age: 3
##行内写法
student2: {name: yhr, age: 3}
##数组
pets1:
- cat
- dog
- pig
##行内写法
pets2: [cat, dog, pig]
实现属性注入
- Spring中提供
Value注解实现属性注入,但YAML可以实现批量注入、松散绑定(横杠和驼峰命名法一致)、JSP303数据校验、复杂类型封装等功能,只是不支持SpEL(Spring Expression Language) - 编写实体类,除开lombok的注解外,
@Component表示是一个Spring组件,@ConfigurationProperties(prefix = "person")表示从YAML配置文件中的person对象取值
//Person.java
@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String name;
private Integer age;
private Boolean happy;
private Date birth;
private Map<String, Object> map;
private List<Object> list;
private Dog dog;
}
//Dog.java
@Data
@NoArgsConstructor
@AllArgsConstructor
@Component
public class Dog {
private String name;
private Integer age;
}
- 编写application.yaml配置文件
person:
name: yhr
age: 23
happy: false
birth: 2021/2/11
map: {k1: v1, k2: v2}
list:
- coding
- music
- girl
dog:
name: 小白
age: 3
- 测试,需要用
@Autowired注解实现自动注入
@Autowired
private Person person;
@Test
void contextLoads() {
System.out.println(person);
}
- 注意,导入一下依赖,可以让
@ConfigurationProperties注解有提示,但不导入也不影响使用
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
- YAML中可以用
${random.int}、${random.uuid}等随机值,也可以使用${person.hello:defaultValue}在前面的值不存在时取默认值
JSR303校验
- 导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
- 实体类上加入
@Validated注解 - 属性上加注解限制其赋值,如
@Email(message = "邮箱格式错误") - 还可以使用
@NotNull,@Min(value),@Max(value),@Size(max, min)等 - 甚至能使用正则表达式
@Pattern(value)
配置文件位置
-
多个配置文件优先级按以下顺序:
- 项目目录
- file: ./config/
- file: ./
- resources目录
- classpath:/config/
- classpath:/
- 项目目录
-
多环境配置(properties):
application.properties中的spring.profiles.active属性选择激活哪个配置文件,对应文件需在同目录下,且名为application-xxx.properties,属性值只需写xxx即可
-
YAML的多环境配置:
spring:
profiles:
active: xxx

浙公网安备 33010602011771号