Spring Boot 自动配置
目录
Spring Boot 自动配置
1.1 @SpringBootApplication注解
1.2 @ConfigurationProperties注解
方式一 : 使用@Value一个个注入
方式二 : 使用@ConfigurationProperties批量注入
方式三:对象属性注入
1.3 条件化配置注解
1.4 自动配置原理
1.4 自动配置原理
1.4.1 加载spring.factories
1.4.2 读取自动配置类
1.4.3 默认属性配置
1.1 @SpringBootApplication注解
- @SpringBootConfiguration : 代表这个类就是一个配置类 , 本质上就是一个@Configuration注解
- @ComponentScan : 组件扫描, 默认扫描启动类所在包及子包下的类身上的注解
- @EnableAutoConfiguration : 自动配置注解 , 添加了此注解会自动去读取spring.factories配置文件中的自动配置类
1.2 @ConfigurationProperties注解
@ConfigurationProperties是SpringBoot提供的重要注解, 他可以将一些配置属性**批量**注入到bean对象。
application.yml配置文件
spring:
jdbc:
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql:///springboot_hello
username: root
password: 123456
profiles:
active: pro
DataSourceProperties.java
public class DataSourceProperties {
private String driverClassName;
private String url;
private String username;
private String password;
// 省略getter和setter和toString.....
}
方式一 : 使用@Value一个个注入
这种注入方式,如果属性特别多,一个一个注入太麻烦啦o(╥﹏╥)o
@Component
public class DataSourceProperties {
@Value("${spring.jdbc.datasource.driverClassName}")
private String driverClassName;
@Value("${spring.jdbc.datasource.url}")
private String url;
@Value("${spring.jdbc.datasource.username}")
private String username;
@Value("${spring.jdbc.datasource.password}")
private String password;
// 省略getter和setter和toString.....
}
方式二 : 使用@ConfigurationProperties批量注入
这种注入方式,属性再多,只要按照规则就可以一次性自动注入。方便的很哦\(^o^)/~
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "spring.jdbc.datasource")
public class DataSourceProperties2 {
private String driverClassName;
private String url;
private String username;
private String password;
// 省略getter和setter和toString.....
}
- 在类上通过@ConfigurationProperties注解声明该类要读取属性配置
- prefix="spring.jdbc.datasource"?读取属性文件中前缀为spring.jdbc.datasource的值。前缀和属性名称和配置文件中的key必须要保持一致才可以注入成功
- Spring Boot默认读取application.properties属性文件
开启@ConfigurationProperties注解使用
import org.example.properties.DataSourceProperties2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author bjk
* @date 2022/10/11 13:25
*/
@RestController
@EnableConfigurationProperties(DataSourceProperties2.class)
public class DataSourceController {
@Autowired
private DataSourceProperties2 dataSourceProperties2;
@RequestMapping("datasource2")
public String dataSource2(){
System.out.println(dataSourceProperties2);
return "datasource2";
}
}
使用@EnableConfigurationProperties(DataSourceProperties2.class),开启DataSourceProperties2身上的@ConfigurationProperties注解 , 他就会生效了, 就会帮助我们注入数据了
请求地址:http://localhost:8080/datasource2
打印结果:
?报错提示,不影响代码的运行。想要处理请在pom文件添加配置信息
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
方式三:对象属性注入
**注意 :?@ConfigurationProperties不仅可以自动注入简单类型数据, 也支持对象属性引导 **
新建配置文件?application-jdbc.yml
# 配置数据库连接池信息
spring:
jdbc:
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql:///business
username: business
password: business
type: druid
在?application.yml?配置文件激活刚刚新建的配置文件
# 激活配置文件
spring:
profiles:
active: jdbc
现在有一个类DataSourceProperties3?, 需要将配置文件中的内容直接注入
package org.example.properties;
/**
* @author bjk
* @date 2022/10/11 13:40
*/
public class DataSourceProperties3 {
private String driverClassName;
private String url;
private String username;
private String password;
@Override
public String toString() {
return "DataSourceProperties3{" +
"driverClassName='" + driverClassName + '\'' +
", url='" + url + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
public String getDriverClassName() {
return driverClassName;
}
public void setDriverClassName(String driverClassName) {
this.driverClassName = driverClassName;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
对象属性引导
package org.example.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "spring.jdbc")
public class JdbcProperties {
private DataSourceProperties3 dataSource ; //注意,属性名称。
private String type ;
@Override
public String toString() {
return "JdbcProperties{" +
"dataSource=" + dataSource +
", type='" + type + '\'' +
'}';
}
public DataSourceProperties3 getDataSource() {
return dataSource;
}
public void setDataSource(DataSourceProperties3 dataSource) {
this.dataSource = dataSource;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
在?DataSourceController?添加如下方法
package org.example.controller;
import org.example.properties.DataSourceProperties2;
import org.example.properties.JdbcProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author bjk
* @date 2022/10/11 13:25
*/
@RestController
public class DataSourceController {
@Autowired
private JdbcProperties jdbcProperties;
@RequestMapping("jdbcproperties")
public String jdbcproperties(){
System.out.println(jdbcProperties);
return "jdbcproperties";
}
}
请求:http://localhost:8080/jdbcproperties
打印结果:
1.3 条件化配置注解
我们看到自动配置类上有一些ConditionXxxx注解 , 这些注解的作用就是进行条件化选择
所谓条件化选择就是如果满足条件, 该配置类就生效, 如果不满足该配置类就不生效
常用的条件化选择注解如下 :
注解 | 作用 | @ConditionalOnBean | 如果存在某个Bean, 配置类生效 | @ConditionalOnMissingBean | 如果不存在某个Bean, 配置类生效 | @ConditionalOnClass | 如果存在某个类, 配置类生效 | @ConditionalOnMissingClass | 如果不存在某个类, 配置类生效 | @ConditionalOnProperty | 如果存在某个属性配置, 配置类生效 | @ConditionalOnWebApplication | 如果是一个web应用, 配置类生效 | @ConditionalOnNotWebApplication | 如果不是一个web应用, 配置类生效 |
因为我们配置了DispatcherServlet?满足上面定义的条件, 所以WebMvcAutoConfiguration会生效 , 那么WebMvcAutoConfiguration自动配置类中帮我们配置了什么呢 ?
视图解析器
?处理器适配器(HandlerAdapter)
?这些配置都是我们之前在SpringMVC时需要自己配置的 , 现在Spring Boot框架都已经提前帮我们配置好了 , 所以我们才能使用的那么方便
1.4 自动配置原理
1.4 自动配置原理
1.4.1 加载spring.factories
在**SpringApplication**类构建的时候,有这样一段初始化代码:
?跟进去往下走
?这里发现会通过loadFactoryNames尝试加载一些FactoryName,然后利用createSpringFactoriesInstances将这些加载到的类名进行实例化。 继续跟进loadFactoryNames方法:
?发现此处会利用类加载器加载一个文件:?META-INF/spring.factories?。我们知道,ClassLoader默认是从classpath下读取文件,因此,SpringBoot会在初始化的时候,加载所有classpath:META-INF/spring.factories文件,包括jar包当中的。而在Spring的一个依赖包:spring-boot-autoconfigure中,就有这样的文件:
?我们引入的任何第三方启动器,只要实现自动配置,也都会有类似文件。
1.4.2 读取自动配置类
我们打开**spring.factories**文件
?可以发现以EnableAutoConfiguration接口为key的一系列配置,key所对应的值,就是所有的自动配置类,可以在当前的jar包中找到这些自动配置类:
?几乎涵盖了现在主流的开源框架 , 我们来看一个我们熟悉的,例如SpringMVC,查看mvc 的自动配置类:
?打开WebMvcAutoConfiguration
1.4.3 默认属性配置
配置类我们找到了 , 那么这些默认配置的属性来自哪里呢?
例如 : 我们配置视图解析器的时候需要配置前缀和后缀 , 那么这些配置在哪配置的呢 ?
?通过源码发现, 这个配置是从this.mvcProperties.getView()中读取的 ,this.mvcProperties又是什么呢 ? 我们继续跟踪,发现其实就是定义的一个变量
?这个变量中又有一个View类型的变量 , 这个变量中配置的就是前缀和后缀
?View中的源码如下 :
?可以看到, 默认读取就是这里的前缀和后缀变量的值 , 默认就是null?.
1.4.4 覆盖默认属性配置
如果我们想自己指定视图的前缀和后缀该如何去做呢 ?
我们再看WebMvcAutoConfiguration这个类的声明, 发现这个类身上有这么一个注解, 我们之前也使用过 , 引入了二个配置对象 , 所以我们知道下面成员位置的WebMvcProperties这个成员变量 , 就是从这里来的
?我们再进去看看这两个配置类 , 配置类身上使用ConfigurationProperties读取配置,前缀是spring.mvc?, 所以如果我们在配置文件中配置spring.mvc前缀开头的配置 , 是不是就可以将自己配置的数据注入到这个对象的属性中 !
所以如果想要自己设置视图前缀和后缀就可以这么配置
# 激活配置文件
spring:
mvc:
view:
prefix: /WEB-INF/
suffix: .jsp
修改服务器端口 :
server:
port: 10000
|