在SpringBoot中为了降低耦合度,简化开发,有很多方便的注解,其中@COnfigurationProperties和@ConditionalOnProperties就只个人觉得比较好用的组件中的两个
这个注解可以根据配置文件中的配置绑定相关属性到有这个注解的类上
其中有四个静态方法
@AliasFor("prefix")
String value() default "";
@AliasFor("value")
String prefix() default "";
boolean ignoreInvalidFields() default false;
boolean ignoreUnknownFields() default true;
其中 value() 和prefix()的功能是一样的,只能使用一个,就是我们在配置文件中的前缀,
ignoreInvalidFields(),是否忽略不合法的Field,默认为false,也就是说这个Field的类型如果不匹配,那么启动就会报错
ignoreUnknownFields()是否忽略位置的Field,默认为true,也就是说在对应的类中如果没有找到这个field,程序也不会报错,
使用的时候会有三种方式使用,一般在项目中选择其一就可以了,
1. 和@Service或者@Component之类的注解一起同时使用在类上,如下
@Data
@Service
@ConfigurationProperties(prefix =LouisBootProperties.PREFIX)
public class LouisBootProperties {
static final String PREFIX = "louis.boot";
private int bootTime;
private String appName;
private int port;
}
2. 在@Configuration,中注入一个新@Bean
@Data
@ConfigurationProperties(prefix =LouisBootProperties.PREFIX)
public class LouisBootProperties {
static final String PREFIX = "louis.boot";
private int bootTime;
private String appName;
private int port;
}
@Configuration
public class BootConfig {
@Bean
public LouisBootProperties louisBootProperties() {
return new LouisBootProperties();
}
}
3. 在@Configuration类上使用@EnableConfigurationProperties(LouisBootProperties.class)
@Data
@ConfigurationProperties(prefix =LouisBootProperties.PREFIX)
public class LouisBootProperties {
static final String PREFIX = "louis.boot";
private int bootTime;
private String appName;
private int port;
}
@Configuration
@EnableConfigurationProperties(LouisBootProperties.class)
public class BootConfig {
}
这三种方式中任意一种方式都可以。
我的配置文件application.properties中的配置如下
louis.boot.port=9999
louis.boot.app-name=LOUIS-server
louis.boot.boot-time=1984
需要注意的是我们的属性一般是驼峰命名法,在配置文件中需要将中间的大写字母换成 "-"加小写字母,不过使用驼峰的方式也是一样的,能够加载出来
Controller类在最下面,
最后结果为
{
"message": "success",
"code": 200,
"result": {
"bootTime": 1984,
"appName": "LOUIS-server",
"port": 9999
}
}
以上三种方式任选一种都是这种结果,如果不选,那么启动会报错(主要原因是@Autowired中的类Spring没有找到的原因,去掉Autowire则不会报错)
有时候我们在项目中不单单只用@ConfigurationProperties,还会和@Conditionl系列配合使用,特别是在Configuration类中,这里介绍一下@ConditionalOnProperty
@ConditionalOnPropertiy 是基于@Conditional的,不懂的可以网上百度,这里简单讲讲
@Conditional 说直白点就是在不同的条件下使用不同的Bean,@Conditional中只有一个参数,如下
Class<? extends Condition>[] value();
这个参数是接收一个实现了Cndition接口的Class数组
而Condition 是一个函数式接口只有一个方法matchs,传入两个参数,返回boolean类型
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
也就是说@ConDitional中的参数会有一个返回值,如果返回true
,我们注解上的组件,就会被加载,否则,Spring则不加载我们注解的组件。
同理,@ConditionalOnPropertiy就是在配置文件找到我们自定义了配置,找到了就返回true,我们注解的组件就会被加载(一般是Configuration类就会生效),否则就不会加载我们注解的组件
Spring Boot中基于@Conditional的注解还有很多,譬如说ConditionalOnMissingClass
、ConditionalOnExpression
等都是同等道理的
@ConditionalOnProperty
的用法很简单,它有五个静态方法,代码如下
String[] value() default {};
String prefix() default "";
String[] name() default {};
String havingValue() default "";
boolean matchIfMissing() default false;
其中 value()
和name()
的用法是一样的,只能使用一个,系统在加载的时候会在配置文件中找value()
或者name()中的值,如果有就返回true,没有就返回false,
prefix()
,就是要找的name()
的前缀,
havingValue()
:如果从配置文件中找到的name()
中的值如果和havingValue()
中的值一样,就返回true,否则就返回false
,
matchIfMissing()
,如果没有找到name()
中的值就返回false
(默认的,我们可以修改)
最后如果返回的值为false
,那么我们注解的类就不会生效,否则就生效
示例代码如下
和@ConfigurationProperties中的代码配套阅读效果更佳
/**
*这个properties我使用@Service的方式
*/
@Data
@Service
@ConfigurationProperties(prefix =LouisBootProperties.PREFIX)
public class LouisBootProperties {
static final String PREFIX = "louis.boot";
private int bootTime;
private String appName;
private int port;
public int getBootTime() {
return bootTime;
}
}
/**
*这个里面我在配置文件中shiyong@Bean的方式
*/
@Data
@ConfigurationProperties(prefix =BootLouisProperties.PREFIX)
public class BootLouisProperties {
static final String PREFIX = "boot.louis";
private String boot;
private String louis;
private long time;
private int port;
}
/**
*配置类
*/
@ConditionalOnProperty(prefix = "louis.config",name = "app-config",havingValue = "app-config")
@Configuration
public class BootConfig {
@Bean
public BootLouisProperties bootLouisProperties() {
return new BootLouisProperties();
}
}
/**
* controller类
*/
@RestController
public class ConfigController {
@Autowired
private LouisBootProperties bootProperties;
@Autowired(required = false)
private BootLouisProperties bootLouisProperties;
@GetMapping("/louis/boot")
public ResponseData getProperties() {
return new ResponseData<>(bootProperties);
}
@GetMapping("/boot/louis")
public ResponseData getBootLouisProperties() {
return new ResponseData<>(bootLouisProperties);
}
}
配置文件
louis.boot.port=9999
louis.boot.app-name=LOUIS-server
louis.boot.boot-time=1984
boot.louis.boot=boot
boot.louis.louis=louis
boot.louis.time=990990
boot.louis.port=582
louis.config.app-config=zhangsan
运行/boot/louis
结果为
{
"message": "success",
"code": 200,
"result": null
}
运行/louis/boot
结果为
{
"message": "success",
"code": 200,
"result": {
"bootTime": 1984,
"appName": "LOUIS-server",
"port": 9999
}
}
说明我们刚才讲解时正确的,BootConfig类是没有生效的