本文使用Spring Boot 版本:org.springframework.boot:spring-boot-autoconfigure:2.3.1RELEASE
起步依赖本质上是一个Maven项目对象模型(Project Object Model,POM),定义了对其它库的传递依赖,通过这些依赖的组合支持某项功能。这个在起步依赖的命名上是有所体现的。
在Spring Boot项目的源码中我们可以看到spring-boot-starters的子项目
打开其中的任意一个子项目,只有一个build.gradle文件:
plugins {
id "org.springframework.boot.starter"
}
description = "Starter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded container"
dependencies {
api(project(":spring-boot-project:spring-boot-starters:spring-boot-starter"))
api(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-json"))
api(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-tomcat"))
api("org.springframework:spring-web")
api("org.springframework:spring-webmvc")
}
在这里能看到起步依赖相关的传递依赖。
起步依赖的版本是由正在使用的Spring Boot的版本来决定的,所以我们不需要指定起步依赖的版本,而起步依赖会决定它们引入的传递依赖的版本。
可以在构建工具中找到所用依赖的版本,在IDEA工具中能看到类似下图的依赖树:
可以通过构建工具中的功能,排除传递依赖,也可以为起步依赖没有涵盖的库指定依赖
在Gradle中排除传递依赖,build.gradle文件:
implementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
覆盖起步依赖引入的传递依赖的版本号,这里需要注意的是Grad了更倾向于使用最新的版本,如果指明的依赖版本高于起步依赖引入的传递依赖的版本号,则不需要排除起步依赖引入的传递依赖,反之,则需要排除起步依赖引入的传递依赖
在Gradle中覆盖起步依赖,build.gradle文件:
implementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
implementation('org.junit.vintage:junit-vintage-engine:版本号')
自动配置中使用的 条件化注解(Spring4.0新特性)
条件化注解 | 配置生效说明 |
---|---|
@ConditionalOnBean | 配置了某个特定的Bean |
@ConditionalOnMissingBean | 没有配置特定的Bean |
@ConditionalOnClass | Classpath里有指定的类 |
@ConditionalOnMissingClass | Classpath里缺少指定的类 |
@ConditionalOnExpression | 给定的Spring Expression Language (SpEL) 表达式计算结果为true |
@ConditionalOnJava | Java的版本匹配特定值或者一个范围值 |
@ConditionalOnJndi | 参数中给定的JNDI位置必须存在一个,如果没有给参数,则要有JNDI InitialContext |
@ConditionalOnProperty | 指定的配置属性要有一个明确的值 |
@ConditionalOnResource | Classpath里有指定的资源 |
@ConditionalOnWebApplication | 这是一个Web应用程序 |
@ConditionalOnNotWebApplication | 这不是一个Web应用程序 |
自动配置是应用程序启动时,根据各种因素决定Spring使用哪个配置的过程。
每当应用程序启动的时候,Spring Boot的自动配置都要判断类似:
配置是Spring Framework的核心元素,所以必须有一个什么东西来告诉Spring如何运行应用程序。在向应用程序加入Spring Boot的时,引入了一个名为spring-boot-autoconfigure的JAR文件,这个文件包含了许多的配置类,这些利用Spring 4.0引入的 条件化配置 新特性的类决定了应用程序在启动的时候使用哪些配置。
覆盖一个自动配置需要显式地写一段配置,那么我们如何知道这段显示的配置该如何编写呢。
大部分的情况下@ConditionalOnMissingBean注解是覆盖自动配置的关键。
比如Spring Security,自动配置的时候会考虑几个配置类,其中最重要的一个类是security.servlet包下的SpringBootWebSecurityConfiguration,代码片段如下:
类路径:org.springframework.boot.autoconfigure.security.servlet.SpringBootWebSecurityConfiguration
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(WebSecurityConfigurerAdapter.class)
@ConditionalOnMissingBean(WebSecurityConfigurerAdapter.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
public class SpringBootWebSecurityConfiguration {
@Configuration(proxyBeanMethods = false)
@Order(SecurityProperties.BASIC_AUTH_ORDER)
static class DefaultConfigurerAdapter extends WebSecurityConfigurerAdapter {
}
}
注解@ConditionalOnMissingBean显示没有配置WebSecurityConfigurerAdapter类型Bean时,自动配置会生效,那么我们就显式地编写一个Java形式的配置类继承WebSecurityConfigurerAdapter并且使用@Configuration注解,那么@ConditionalOnMissingBean的条件就会不成立,SpringBootWebSecurityConfiguration提供的配置就会跳过。
示例代码如下
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private ReaderRepository readerRepository;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//TODO 重写的具体内容
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//TODO 重写的具体内容
}
}
Spring Boot获得属性的属性源(常见的):
application.properties或application.yml文件可以存放的位置
Spring Boot自动配置的很多组件添加了@ConfigurationProperties注解,所以可以通过Spring Boot支持的各种数据源对属性进行配置。
例如类路径:org.springframework.boot.autoconfigure.jdbc.DataSourceProperties
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {
说明Spring Boot支持带spring.datasource前缀的属性,具体支持的属性可以看到类里面的属性。
Spring Boot 自动配置的Bean提供了300多个用于微调的属性,比如将Thymeleaf模板禁用,那么只需要将spring.thymeleaf.cache设置为false即可
yml文件配置类似如下:
spring:
thymeleaf:
cache: false
从技术上说:@ConfigurationProperties注解不会生效,通过源代码我们能看到Spring Boot自动配置相关的配置类已经加上了@EnableConfigurationProperties注解,所以除非完全不使用自动配置,否则不需要显式地添加@EnableConfigurationProperties注解。
当应用程序需要部署到不同的运行环境是,一些配置细节通常会有点不一样,比如开发环境的数据库与生产环境的会使用不同的数据库。Spring Framework从Spring 3.1开始支持基于Profile的配置。
那么如何配置Profile呢?
spring:
profiles:
active: production
logging:
level:
root: INFO
---
spring:
profiles: development
logging:
level:
root: DEBUG