目录
用于"环境隔离",能够快速切换开发环境(dev),测试环境(test),生产环境(prod)等
针对不同的环境,往SpringIOC容器中注册不同的组件
@Profile({"dev","test"})注解可以配合@Component等注解使用,也可以配合@Bean注解使用,标记当前组件在指定环境下生效
没有标@Profile的类,在任何环境下都生效
@Profile对于@EnableConfigurationProperties({Dog.class,Cat.class})中的Dog类、Cat类不生效(即Dog类用了@Profile也会被注册进SpirngIOC)
在properties.yaml文件中激活对应的环境,如果没有配置对应的"激活环境",则SpringBoot默认激活default环境; 如果配置了"激活环境",则default环境失效
- spring:
- profiles:
- active: dev,test
针对不同的环境,选择生效的"副配置文件"(主配置文件application.yaml永远生效)
例如:application-dev.yaml、application-test.yaml、application-prod.yaml
激活方式与1.1.2相同,且只能写在主配置文件中:
例如:spring.profiles.active=dev,则application-dev.yaml生效
如果"副配置文件"和"主配置文件"配置冲突,以"副配置文件"为准
命令行 > 包内外 (例: java -jar demo.jar --server.port=9999)
jar包外配置优先级 > jar包内配置优先级
副配置优先级 > 主配置优先级
- 包内:(1)application.yaml #server.port=8000
- (2)application-dev.yaml #server.port=8001
- 包外:(3)application.yaml #server.port=9000
- (4)application-dev.yaml #server.port=9001
-
- //有(1),以(1)为准
- //有(1)(2),以(2)为准
- //有(1)(2)(3),以(2)为准
- //有(1)(2)(3)(4),以(4)为准
-
- //执行的是命令行,以命令行为准
根据"配置优先级"的规则,当需要修改某一项配置,无需再重新打jar包部署,而只需要新建一个与jar包文件同级别的"外部配置文件",然后用java -jar命令再次执行jar包即可
当我们在编写多个模块时,往往有许多重复代码,可以考虑将这些重复代码抽取出来作为一个starter,然后让模块去引用此starter即可
新建一个parent父模块管理众多子模块,此模块只有一个pom.xml(打包方式为pom)文件,用于引入spring-boot-starter-parent和各种依赖(这样子模块就无需再引入了)
在yaml中配置SpringBoot官方给的配置,当输入相关值的时候,会有提示
而一些自定义的配置(例如:属性绑定时),则在yaml文件中不会有提示,而且被属性绑定的类还会被IDEA标红提示
只需要引入spring提供的starter即可解决
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-configuration-processorartifactId>
- <optional>trueoptional>
- dependency>
(1) 创建公共模块,可以起名为xxx-xxx-spring-boot-starter
(2) 抽取公共代码
(3) 因为SpringBoot默认只会扫描自己主程序的包,外部引入的依赖包不会被扫描到,所以:
在【公共模块】的Spring配置类中,用@import或@Bean引入需要注册的组件(如Controller,Service,pojo等)
在【普通模块】引入【公共模块】后,在Spring配置类中用@Import或@Bean引入【公共模块】的Spring配置类
- //【自动配置类】
- @SpringBootConfiguration
- @ComponentScan("starter.xyz.aboluo")
- //因为这些类在【普通模块】中不会被扫描到,所以全部引入到Spring配置类中
- @Import({HelloController.class, HelloServiceImpl.class})
- @EnableConfigurationProperties({Hello.class})
- public class AboluoHelloAutoConfiguration {
- }
-
- //【配置属性类】
- //@Component 因为在Spring配置类中被用@EnableConfigurationProperties引入了,此注解可以不写
- @ConfigurationProperties(prefix = "hello")
- public class HelloProperties {
- private String welcomeMessage;
- private String companyName;
- }
-
- //【普通模块】的Spring配置类中用@Import引入【公共模块】的Spring配置类
- @SpringBootConfiguration
- @MapperScan("xyz.aboluo.dao")
- @Import(AboluoHelloAutoConfiguration.class)
- public class SpringConfig {
- }
-
- // 在yaml中对Hello类进行"属性绑定"
- hello:
- welcome-message: 欢迎您的使用!
- company-name: 字节跳动
-
- //此时依赖【公共模块】的【普通模块】启动后,就可以访问到"问候接口/hello/welcome"
使用3.1的抽取方式的弊端:【普通模块】引入【公共模块】后,需要在Spring配置类上用@Import引入【公共模块】的Spring配置类
利用Enable机制,可以在【公共模块】中自定义一个@EnableXxx注解,【普通模块】在Spring配置类使用【公共模块】的自定义注解即可,无需再使用@Import了
- //【公共模块】自定义注解
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.TYPE})
- @Documented
- @Import({HelloController.class, HelloServiceImpl.class, Hello.class})
- public @interface EnableHello {
- }
-
- //【普通模块】的Spring配置类上使用"自定义注解"
- @SpringBootConfiguration
- @MapperScan("xyz.aboluo.dao")
- @EnableHello
- public class SpringConfig {
- }
(Java的SPI默认访问META-INF/services/目录下的文件)
(SpringBoot的SPI默认访问META-INF/spring/目录下的文件)
项目引入官方starter依赖时,这个starter会继续依赖spring-boot-starter,其中一个核心依赖是spring-boot-autoconfigure,此时SpirngBoot会触发一个行为,自动去找org.springframework.boot:spring-boot-autoconfigure包META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件
此文件中所有的类(自动配置类一般写为XxxAutoConfiguration)会在项目启动时自动加载(被注册进SpringIOC),主要作用就是向SpringIOC容器中添加一些组件(用@Import或@Bean的方式)
并且会用@EnableConfigurationProperties指定对应的配置属性类,开启属性绑定
使用3.2的抽取方式,还需要在【普通模块】的Spring配置类写"自定义注解",有没有可能连自定义注解也不用写,直接引入【公共模块】就可以用呢?
利用SPI机制,在【公共模块】"类资源文件夹"resource下放META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件,并写入Spring配置类(主要是要其中的@Import)的全限定类名
- //新建resource/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件
- starter.xyz.aboluo.boot.AboluoHelloAutoConfiguration
-
- @SpringBootConfiguration
- @ComponentScan("starter.xyz.aboluo")
- @Import({HelloController.class, HelloServiceImpl.class})
- @EnableConfigurationProperties({HelloProperties.class})
- public class AboluoHelloAutoConfiguration {
- }
parent工程下的B工程依赖A工程,如果在给B工程package时,出现"Failed to collect dependencies at ...",需要先对parent工程进行install后即可