Spring 如何将配置文件中的值保存到静态字段
🏷️ Spring Boot
需求是 在实例化一个对象时,将某个字段的值默认初始化为配置文件中的配置项。
使用到了 @Component
、 @Resource
和 @PostConstruct
三个注解。
首先按照需求增加配置项。
application.yml
# Service
service:
settings:
name: SampleService
再增加对应的配置类,在类上使用 @Component
注解,在字段的 set 方法上使用 @Value
注解注入配置文件中对应的配置项值。
ServiceSettings.java
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* 服务配置类
*/
@Component
public class ServiceSettings {
/**
* 服务名
*/
private String name;
/**
* 服务名
*/
public String getName() {
return name;
}
@Value("${service.settings.name}")
public void setName(String name) {
this.name = name;
}
}
在模型类上使用 @Component
注解,在私有字段上使用 @Resource
注解注入配置类的实例,另外使用 @PostConstruct
注解为静态的配置类字段赋值。
从 Java EE5 规范开始,Servlet 增加了两个影响 Servlet 生命周期的注解(Annotation):
@PostConstruct
和@PreDestroy
。这两个注解被用来修饰一个非静态的 void 方法.而且这个方法不能有抛出异常声明。@PostConstruct 说明
被@PostConstruct
修饰的方法会在服务器加载 Servlet 的时候运行,并且只会被服务器调用一次,类似于 Servlet 的init()
方法。被@PostConstruct
修饰的方法会在构造函数之后,Servlet 的init()
方法之前运行。
SampleEntity.java
import com.octopus.middle.common.settings.ServiceSettings;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
@Component
public class SampleEntity {
@Resource
private ServiceSettings initServiceSettings;
private static ServiceSettings serviceSettings;
@PostConstruct
public void init() {
serviceSettings = initServiceSettings;
}
/**
* 服务名
*/
private String serviceName = serviceSettings != null ? serviceSettings.getName() : null;
/**
* 服务名
*/
public String getServiceName() {
return serviceName;
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
}
在执行 @PostConstruct
方法前会先实例化 SampleEntity
类,此时 initServiceSettings 和 serviceSettings 均为 null
。
实例化之后再调用实例方法 init()
,此时 initServiceSettings 有值,serviceSettings 为 null。
在此方法中将使用 @Resource
注解注入的字段(initServiceSettings)值赋给静态变量(serviceSettings),这样就可以在之后的处理中直接使用了。
之后在代码中通过 new
关键字创建实例 (new SampleEntity()
) 时,serviceName 字段就可以直接获取到配置文件中的值了。
如果模型组件不在同一个模块中,需要使用 @ComponentScan
注解扫描组件。示例如下:
@ComponentScan(basePackages = { "com.xxxx.xxx.common" })
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}