首先简单说一下两个注解之前的区别。
| @Configurationproperties | @Value | |
| 功能 | 批量注入配置文件中的属性 | 每个属性单独注入 |
| 松散语法 | 支持 | 不支持 |
| SpEL | 不支持 | 支持 |
| JSR303数据校验 | 支持 | 不支持 |
| 复杂类型封装 | 支持 | 不支持 |
首先说一下功能上面,@Configurationproperties只需要在类上面标明,便可以针对该类的所有属性批量注入,而@Value却需要在每个属性上面单独注入。
其次,松散语法是指使用"-"或者"_"以及驼峰命名之间自动转变,@Value并不支持
SpEL语法和JSR303数据校验以及复杂类型封装就没有什么好说了的。
下面上代码,老样子,首先是pom.xml
<?xml version="1.0" encoding="UTF-8"?> <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.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>cc.acme_me</groupId> <artifactId>spring-boot-annotation</artifactId> <version>0.0.1-SNAPSHOT</version> <name>spring-boot-annotation</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
这次先把配置文件放在前面,使用properties来配置属性
server.port=8080 ################User################ user.id=1 user.user-name=admin user.email=springboot#acme-me.cc
这次少配置东西,少一点属性方便观察。
接着是Entity的User类
package cc.acme_me.springbootannotation.entity;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.validation.constraints.Email;
/**
* User entity
*
* @author acme
* @Component 标识注入Spring容器中(只有注入Spring容器才能使用)
*/
@Component
public class User {
@Value("${user.id}")//获取配置文件中的值
private Integer id;
@Value("${user.user-name}")//获取配置文件中的值
//@Value("${user.userName}")//获取配置文件中的值 不支持
private String userName;
@Value("123")//字面量直接注入
private String password;
@Value("#{15*3}")//SpEL表达式
private Integer privilegeLevel;
@Email//在@Value下并不生效
@Value("${user.email}")//获取邮件
private String email;
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + '\'' +
", password='" + password + '\'' +
", privilegeLevel=" + privilegeLevel +
", email='" + email + '\'' +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getPrivilegeLevel() {
return privilegeLevel;
}
public void setPrivilegeLevel(Integer privilegeLevel) {
this.privilegeLevel = privilegeLevel;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}按照上面的内容我们运行测试类
package cc.acme_me.springbootannotation;
import cc.acme_me.springbootannotation.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootAnnotationApplicationTests {
@Autowired
private User user;
@Test
public void contextLoads() {
System.out.println(user);
}
}
会发现测试通过了,可以看到这里emal的值并不是一个正确的邮箱地址,说明@Email校验在@Value下并未生效。
现在我们将User进行修改,使用@
package cc.acme_me.springbootannotation.entity;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.Email;
/**
* User entity
*
* @author acme
* @ConfigurationProperties 注解用于标识注释参数 prefix标识对应的前缀
* @Component 标识注入Spring容器中(只有注入Spring容器才能使用)
*/
@ConfigurationProperties(prefix = "user")
@Validated
@Component
public class User {
private Integer id;
private String userName;
private String password;
private Integer privilegeLevel;
@Email
private String email;
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + '\'' +
", password='" + password + '\'' +
", privilegeLevel=" + privilegeLevel +
", email='" + email + '\'' +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getPrivilegeLevel() {
return privilegeLevel;
}
public void setPrivilegeLevel(Integer privilegeLevel) {
this.privilegeLevel = privilegeLevel;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}再次运行测试类,会发现控制台报错了。
报错的位置加载user注入的时候出现了问题
而且如果拉到最后面,还有更明显的提示Binding validation errors on user- Field error in object 'user' on field 'email': rejected value [springboot#acme-me.cc];
这里已经说了是email这个属性校验失败,拉到最后其实还有很好的中文提示:
这已经告诉了说不是一个合法的邮件地址,说明校验在@ConfigurationProperties下是有效的。
我们更改application.properties文件中的user.email属性
application.properties
其它属性不变,再次运行测试类
会发现绿条一次通过,至于password和privilegeLevel为null,是因为我们配置文件中没有这两个文件,所以这两个文件现在为空。
最后,我们发现两个都能用,那么不得折腾一下吗?如果两个注解都配置了,可以一起用吗?
如果其中某个属性在配置文件中有值,而在属性上使用@Value的字面量去设置值,那么这个属性的值会是配置文件中的还是@Value注入进来的呢?
这里更改一下application.properties文件
server.port=8080 ################User################ user.id=1 user.user-name=admin [email protected] user.password=123
在更改一下User类
package cc.acme_me.springbootannotation.entity;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.Email;
/**
* User entity
*
* @author acme
* @ConfigurationProperties 注解用于标识注释参数 prefix标识对应的前缀
* @Component 标识注入Spring容器中(只有注入Spring容器才能使用)
*/
@ConfigurationProperties(prefix = "user")
@Validated
@Component
public class User {
private Integer id;
private String userName;
@Value("321")//properties文件也配置了这个属性,运行测试类这里会获取哪个值呢?
private String password;
@Value("#{3*3}")
private Integer privilegeLevel;
@Email
private String email;
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + '\'' +
", password='" + password + '\'' +
", privilegeLevel=" + privilegeLevel +
", email='" + email + '\'' +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getPrivilegeLevel() {
return privilegeLevel;
}
public void setPrivilegeLevel(Integer privilegeLevel) {
this.privilegeLevel = privilegeLevel;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}上测试结果!
最后的最后,在这里说一下使用原则:在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;如果专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;
acme