SpringBoot实战课堂笔记Spring Boot 核心之(起步依赖+自动配置)

文章目录

  • 起步依赖
      • 1. 指定基于功能的依赖
      • 2. 覆盖起步依赖引入的传递依赖
  • 自动配置
    • 1.自动配置
    • 2.自定义配置
      • 2.1覆盖 Spring Boot 自动配置
      • 2.2自动配置微调

本文使用Spring Boot 版本:org.springframework.boot:spring-boot-autoconfigure:2.3.1RELEASE

起步依赖

起步依赖本质上是一个Maven项目对象模型(Project Object Model,POM),定义了对其它库的传递依赖,通过这些依赖的组合支持某项功能。这个在起步依赖的命名上是有所体现的。
在Spring Boot项目的源码中我们可以看到spring-boot-starters的子项目
SpringBoot实战课堂笔记Spring Boot 核心之(起步依赖+自动配置)_第1张图片
打开其中的任意一个子项目,只有一个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")
}

在这里能看到起步依赖相关的传递依赖。

1. 指定基于功能的依赖

起步依赖的版本是由正在使用的Spring Boot的版本来决定的,所以我们不需要指定起步依赖的版本,而起步依赖会决定它们引入的传递依赖的版本。
可以在构建工具中找到所用依赖的版本,在IDEA工具中能看到类似下图的依赖树:
SpringBoot实战课堂笔记Spring Boot 核心之(起步依赖+自动配置)_第2张图片

2. 覆盖起步依赖引入的传递依赖

可以通过构建工具中的功能,排除传递依赖,也可以为起步依赖没有涵盖的库指定依赖

在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应用程序

1.自动配置

自动配置是应用程序启动时,根据各种因素决定Spring使用哪个配置的过程。
每当应用程序启动的时候,Spring Boot的自动配置都要判断类似:

  • Spring的JdbcTemplate是否在Classpath里?如果是,并且有DataSource的配置,那么自动配置一个JdbcTemplate的Bean。
  • Thymeleaf是否在Classpath里?如果是,则配置Thymeleaf的模板解析器、视图解析器以及模板引擎。
    等等涵盖安全、集成、持久化、Web开发等诸多方面。

配置是Spring Framework的核心元素,所以必须有一个什么东西来告诉Spring如何运行应用程序。在向应用程序加入Spring Boot的时,引入了一个名为spring-boot-autoconfigure的JAR文件,这个文件包含了许多的配置类,这些利用Spring 4.0引入的 条件化配置 新特性的类决定了应用程序在启动的时候使用哪些配置。

2.自定义配置

2.1覆盖 Spring Boot 自动配置

覆盖一个自动配置需要显式地写一段配置,那么我们如何知道这段显示的配置该如何编写呢。
大部分的情况下@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 重写的具体内容
    }
}

2.2自动配置微调

Spring Boot获得属性的属性源(常见的):

  1. 命令行参数
  2. 应用程序外的application.properties或application.yml文件
  3. 打包在应用程序内的application.properties或application.yml文件
  4. 通过@PropertySource标注的属性源
  5. 默认属性

application.properties或application.yml文件可以存放的位置

  1. 外置,相对于应用程序运行目录的/config子目录
  2. 外置, 应用程序运行运行目录
  3. 内置,在config包内
  4. 内置, 在Classpath跟目录

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呢?

  1. 激活Profile:向application.yml添加spring.profiles.active属性
spring:
	profiles:
		active: production
  1. 如果使用的是application.properties,可以创建额外的属性文件,遵循application-{profile}.properties这种命名格式。
    如果是使用YAML配置属性,除了支持 application.properties这种方式,还支持在同一个application.yml文件中使用三个连字符(—)作为分隔符,然后通过spring.profiles指定值的方式配置:
logging:
	level:
		root: INFO
---
spring:
	profiles: development
logging:
	level:
		root: DEBUG

你可能感兴趣的:(java,后端,spring,boot)