为了方便多环境适配,SpringBoot简化了profile功能。
默认配置文件application.yaml任何时候都会加载。
指定环境配置文件application-{env}.yaml
application-test.yaml
person:
name: test-张三
server:
port: 7000
application-prod.yaml
person:
name: prod-张三
server:
port: 8000
激活指定环境
➢ 配置文件激活
application.properties
# 激活prod配置文件(指定激活的环境,默认配置文件和指定环境的配置文件都会生效)
spring.profiles.active=prod
➢ 命令行激活:java -jar xxx.jar --spring.profiles.active=prod --person.name=haha
◽️ 修改配置文件的任意值,命令行优先
默认配置与环境配置同时生效
同名配置项,profile配置优先
public interface Person {
String getName();
Integer getAge();
}
@Profile("test") // 加载application-test.yaml里的
@Component
@ConfigurationProperties("person")
@Data
public class Worker implements Person {
private String name;
private Integer age;
}
@Profile(value = {"prod", "default"}) // 加载application-prod.yaml里的
@Component
@ConfigurationProperties("person")
@Data
public class Boss implements Person {
private String name;
private Integer age;
}
Controller
@RestController
public class HelloController {
@Autowired
private Person person;
@GetMapping("/")
public String hello() {
return person.getClass().toString();
}
}
@Profile还可以修饰在方法上
class Color {
}
@Configuration
public class MyConfig {
@Profile("prod") // 标志在方法上 指定的环境 这个方法组件才生效
@Bean
public Color red() {
return new Color();
}
@Profile("test")
@Bean
public Color green() {
return new Color();
}
}
spring.profiles.active=production
spring.profiles.group.production[0]=proddb
spring.profiles.group.production[1]=prodmq
# 使用:--spring.profiles.active=production 激活
官方文档 - Externalized Configuration
Spring Boot使用一个非常特殊的PropertySource顺序,该顺序旨在允许合理地重写值。属性按以下顺序考虑(较低项的值优先于较早项的值):
SpringApplication.setDefaultProperties).@PropertySource annotations on your @Configuration classes. Please note that such property sources are not added to the Environment until the application context is being refreshed. This is too late to configure certain properties such as logging.* and spring.main.* which are read before refresh begins.application.properties files)RandomValuePropertySource that has properties only in random.*.System.getProperties()).java:comp/env.ServletContext init parameters.ServletConfig init parameters.SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property).properties attribute on your tests. Available on @SpringBootTest and the test annotations for testing a particular slice of your application.@TestPropertySource annotations on your tests.$HOME/.config/spring-boot directory when devtools is active.为了提供一个具体示例,假设您开发了一个使用name属性的@组件,如以下示例所示:
import org.springframework.stereotype.*;
import org.springframework.beans.factory.annotation.*;
@Component
public class MyBean {
@Value("${name}")
private String name;
// ...
}
Spring Boot允许您将配置外部化,以便您可以在不同的环境中使用相同的应用程序代码。
您可以使用各种外部配置源,包括 Java properties文件、YAML文件、环境变量 和 命令行参数。
Spring Boot将自动查找并加载应用程序、特性和应用。应用程序启动时,来自以下位置的yaml文件:
列表按优先级排序(较低项的值优先于较早项)。加载文件中的文档作为PropertySources添加到Spring环境中。
application.properties和application.yml。application-{profile}.properties 和 application-{profile}.yml。application.properties和application.yml。application-{profile}.properties和application-{profile}.yml。指定环境优先,外部优先,后面的可以覆盖前面的同名配置项。
autoconfigure包中配置使用META-INF/spring.factories中EnableAutoConfiguration的值,使得项目启动加载指定的自动配置类
编写自动配置类 xxxAutoConfiguration => xxxxProperties
➢ @Configuration
➢ @Conditional
➢ @EnableConfigurationProperties
➢ @Bean
➢ …
引入starter — xxxAutoConfiguration — 容器中放入组件 ---- 绑定xxxProperties ---- 配置项
目标:创建HelloService的自定义starter。
创建两个工程,分别命名为hello-spring-boot-starter(普通Maven工程),hello-spring-boot-starter-autoconfigure(需用用到Spring Initializr创建的Maven工程)。
hello-spring-boot-starter无需编写什么代码,只需让该工程引入hello-spring-boot-starter-autoconfigure依赖:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.atguigugroupId>
<artifactId>hello-spring-boot-starterartifactId>
<version>1.0.0-SNAPSHOTversion>
<dependencies>
<dependency>
<groupId>com.atguigugroupId>
<artifactId>hello-spring-boot-starter-autoconfigureartifactId>
<version>1.0.0-SNAPSHOTversion>
dependency>
dependencies>
project>
hello-spring-boot-starter-autoconfigure的pom.xml如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.4.2version>
<relativePath/>
parent>
<groupId>com.atguigugroupId>
<artifactId>hello-spring-boot-starter-autoconfigureartifactId>
<version>1.0.0-SNAPSHOTversion>
<name>hello-spring-boot-starter-autoconfigurename>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
dependencies>
project>
创建4个文件:
➢ com/atguigu/hello/auto/HelloServiceAutoConfiguration
import com.atguigu.hello.bean.HelloProperties;
import com.atguigu.hello.service.HelloService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties(HelloProperties.class) // 默认HelloProperties放在容器中
public class HelloServiceAutoConfiguration {
@ConditionalOnMissingBean(HelloService.class)
@Bean
public HelloService helloService(){
return new HelloService();
}
}
➢ com/atguigu/hello/bean/HelloProperties
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("hello")
public class HelloProperties {
private String prefix;
private String suffix;
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public String getSuffix() {
return suffix;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}
}
➢ com/atguigu/hello/service/HelloService
import com.atguigu.hello.bean.HelloProperties;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 默认不要放在容器中
*/
public class HelloService {
@Autowired
private HelloProperties helloProperties;
public String sayHello(String userName) {
return helloProperties.getPrefix() + ": " + userName + " > " + helloProperties.getSuffix();
}
}
➢ src/main/resources/META-INF/spring.factories
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.atguigu.hello.auto.HelloServiceAutoConfiguration
用maven插件,将两个工程install到本地。
接下来,测试使用自定义starter,用Spring Initializr创建名为hello-spring-boot-starter-test工程,引入hello-spring-boot-starter依赖,其pom.xml如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.4.2version>
<relativePath/>
parent>
<groupId>com.atguigugroupId>
<artifactId>hello-spring-boot-starter-testartifactId>
<version>1.0.0-SNAPSHOTversion>
<name>hello-spring-boot-starter-testname>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>com.atguigugroupId>
<artifactId>hello-spring-boot-starterartifactId>
<version>1.0.0-SNAPSHOTversion>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
添加配置文件application.properties
hello.prefix=ATGUIGU
hello.suffix=6666
编写新项目的Controller
import com.atguigu.hello.service.HelloService; // 来自自定义starter
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@Autowired
HelloService helloService;
@GetMapping("/hello")
public String sayHello() {
String s = helloService.sayHello("张三");
return s;
}
}
