SpringBoot开发——8种读取配置文件信息的方式
文章目录
- 1. 基于@Value依赖注入
- 2. 基于@ConfigurationProperties
- 3. 注入自定义配置文件属性
- 4. 注入自定义yml格式配置
- 5. 通过Environment获取
- 6. 自定义注解获取配置
- 7. 编程方式获取配置
- 8. 读取命令行参数
1. 基于@Value依赖注入
属性占位符风格依赖注入
pack:
property:
name: xxxooo
age: 66
通过${xxx}
语法进行注入
@Value("${pack.property.name}")
private String name ;
接下来将通过下面的代码进行输出测试
@PostConstruct
private void init() {
System.err.printf("@Value Property Inject name: %s%n", this.name) ;
}
输出结果
@Value Property Inject name: xxxooo
使用非常的简单,这里不仅仅可以在字段上,还可以是参数或者方法上使用@Value
注解
SpEL表达式风格注入
你还可以使用#{xxx}
这种基于SpEL表达式
的语法进行注入
@Value("#{systemProperties['java.home']}")
private String javaHome ;
这里的systemProperties
是Spring容器
中的bean名称
,Spring容器
在初始化时会将系统属性对应的Map集合
注册为Bean对象
。
既然是bean对象
,那么这里也可以这样写:
@Value("#{@systemProperties['java.home']}")
@
符合表示bean
引用。
2. 基于@ConfigurationProperties
外部化配置注释。如果你想将一些外部属性(例如来自.properties文件
)绑定并验证,请在类或@Configuration类
中的@Bean方法
中添加此注释。
pack:
property:
name: xxxooo
age: 66
定义一个bean
@Component
@ConfigurationProperties(prefix = "pack.property")
public class PackProperties {
private String name ;
private Integer age ;
@PostConstruct
private void init() {
System.out.println(this) ;
}
// getters, setters
}
prefix
指定了配置文件中属性前缀
输出结果
PackProperties [name=xxxooo, age=66]
你还可以应用到@Bean注解
的方法上
@Configuration
public class AppConfig {
@Bean
@ConfigurationProperties(prefix = "pack.property")
public PackProperties packProperties() {
return new PackProperties() ;
}
}
这种效果与上面基于类的一样。
3. 注入自定义配置文件属性
要想注入自定义的配置文件(如:app.properties
)中的属性配置,你首先要让容器知道你这配置文件,我们可以采用@PropertySource注解
或@PropertySources注解
,如下示例:
在classes
下新建app.properties
配置文件,内容如下:
pack.app.title=xxx project
pack.app.version=1.0.0
接下来通过@PropertySource注解
加载app.properties
文件
@Configuration
@PropertySource({"app.properties"})
public class PropertySourceConfig {
}
接下来通过@Value
或@ConfigurationProperties
进行注入
@Component
@ConfigurationProperties(prefix = "pack.app")
public class AppProperties {
private String title ;
private String version ;
// getters, setters
}
注:@PropertySource注解不支持yml格式的文件。
4. 注入自定义yml格式配置
要想将yml格式
的配置也添加到当前容器的环境配置中,我们需要借助YamlPropertiesFactoryBean
或YamlMapFactoryBean
这两个FactoryBean
能加载yml文件
将内容分别封装成Properties
和Map对象
。
自定义yml文件
pack:
custom:
address: localhost
port: 8080
如果你希望在容器中像上面使用@Value
或者@ConfigurationProperties
方式注入配置属性,那么你还需要定义下面的环境属性处理器
public class PackEnvironmentPostProcessor implements EnvironmentPostProcessor {
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
YamlPropertiesFactoryBean bean = new YamlPropertiesFactoryBean() ;
bean.setResources(new ClassPathResource("pack.yml")) ;
environment.getPropertySources().addLast(new PropertiesPropertySource("pack", bean.getObject())) ;
}
}
这样配置后你就可以通过@Value
或者@ConfigurationProperties
注入上面yml配置
的属性了。
@Component
@ConfigurationProperties(prefix = "pack.custom")
public class CustomProperties {
private InetAddress address ;
private Integer port ;
@PostConstruct
private void init() {
System.out.println(this) ;
}
// getters, setters
}
输出结果
CustomProperties [address=localhost/127.0.0.1, port=8080]
如果你不需要通过@Value
注解方式获取,那么你可以直接将YamlPropertiesFactoryBean
声明为bean
,在需要用的地方注入对应的Properties
即可,如下示例:
@Bean
YamlPropertiesFactoryBean packYaml(@Value("classpath:pack.yml") Resource resource) {
YamlPropertiesFactoryBean bean = new YamlPropertiesFactoryBean() ;
bean.setResources(resource) ;
return bean ;
}
接下来,你可以在需要的地方直接注入Properties
@Resource
private Properties packYaml ;
如果你想使用Map
,那么你可以使用YamlMapFactoryBean
。
5. 通过Environment获取
对于添加到当前容器中的所有配置属性,你都可以直接通过Environment方式
获取,如下示例:
private final Environment environment ;
public EnvironmentGetProperties(Environment environment) {
this.environment = environment ;
}
@PostConstruct
private void init() {
System.err.printf("pack.custom.port=%s%n", environment.getProperty("pack.custom.port")) ;
}
输出结果
pack.custom.port=8080
上面是通过构造函数注入Environment
,你还可以让你的bean
实现EnvironmentAware接口
。
@Component
public class EnvironmentAwareGetProperties implements EnvironmentAware {
private Environment environment ;
@PostConstruct
private void init() {
System.err.printf("pack.custom.port=%s%n", environment.getProperty("pack.custom.port")) ;
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment ;
}
}
甚至,你还可以通过ApplicationContext
间接的获取
@Component
public class ApplicationContextAwareGetProperties implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
applicationContext.getEnvironment().getProperty("pack.custom.port") ;
}
}
最终,都是通过Environment方式
获取配置属性。
6. 自定义注解获取配置
自定义注解方式,其实还是用到的@Value
,如下示例:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Value("${pack.custom.port}")
public @interface PackValue {
}
在自定义的注解上添加了@Value注解
,同时指定了要获取的属性配置。
接下来,你就可以在你需要的地方直接使用@PackValue注解
了。
@PackValue
private Integer port ;
如果你的项目中使用到此属性的地方比较多,这种方式是不是非常的合适。以后任何的修改只需要修改PackValue注解
中的配置即可。
7. 编程方式获取配置
如果你比较的闲没事干,凑工时,凑代码量,那么你还可以自己通过编程的方式获取配置,如下示例:
public static Properties load(String filename) {
ClassPathResource resource = new ClassPathResource(filename) ;
Properties props = new Properties() ;
try {
props.load(resource.getInputStream()) ;
} catch (IOException e) {
e.printStackTrace();
}
return props ;
}
如果可以你直接吧这个Properties
注册为bean对象
。
8. 读取命令行参数
如果你的配置来自于启动时配置的命令行参数,格式如下:
java jar app.jar --pack.custom.port=9999
如上,通过–前缀指定了命令行的参数,要获取这样的参数你可以通过如下方式:
private final ApplicationArguments args ;
public CommandLineArgument(ApplicationArguments args) {
this.args = args ;
}
@PostConstruct
private void init() {
System.out.println(this.args.getOptionValues("pack.custom.port")) ;
}
在程序代码中,我们可以直接注入ApplicationArguments对象
,该对象可获取应用启动时的任何参数。