- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
在Spring框架中@PropertySource注解是非常常用的一个注解,其主要作用是将外部化配置解析成key-value键值对"存入"Spring容器的Environment环境中,以便在Spring应用中可以通过@Value或者占位符${key}的形式来使用这些配置.
// @PropertySource需要和@Configuration配个使用
// @PropertySource加载的配置文件时需要注意加载的顺序,后面加载的配置会覆盖前面加载的配置
// @PropertySource支持重复注解
// value值不仅支持classpath表达式,还支持任意合法的URI表达式
@Configuration
@PropertySource(value = "classpath:/my.properties",encoding = "UTF8")
@PropertySource(value = "classpath:/my2.properties",encoding = "UTF8",ignoreResourceNotFound = true)
public static class PropertyConfig {
}
@Component
public class App {
@Value("${key1:default-val}")
private String value;
@Value("${key2:default-val2}")
private String value2;
}
下面是配置文件my.properties和my2.properties的具体内容.
# my.properties
key1=自由之路
# my2.properties
key1=程序员
key2=自由之路
Spring容器启动时,会将my.properties和my2.properties的内容加载到Environment中,并在App类的依赖注入环节,将key1和key2的值注入到对应的属性.
阅读@PropertySource的源代码,我们发现还有一个factory属性。从这个属性的字面意思看,我们不难猜测出这个属性设置的是用于产生PropertySource的工厂.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertySources.class)
public @interface PropertySource {
String name() default "";
String[] value();
boolean ignoreResourceNotFound() default false;
String encoding() default "";
Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
}
要深入理解PropertySourceFactory,我们先要知道以下的背景知识.
在Spring中,配置的来源有很多。Spring将配置来源统一抽象成 PropertySource 这个抽象类,Spring中内建的常用的 PropertySource 有以下这些 。
MapPropertySource 。
CommandLinePropertySource 。
PropertiesPropertySource 。
SystemEnvironmentPropertySource 。
ResourcePropertySource 。
ResourcePropertySource这个类将一系列配置来源统一成ResourcePropertySource,可以说是对 PropertySource 的进一步封装.
PropertySourceFactory 接口,用于产生PropertySource。Spring中,PropertySourceFactory 默认的实现是DefaultPropertySourceFactory,用于生产 ResourcePropertySource.
经过上面的介绍,我们知道如果没有配置@PropertySource的factory属性的话,默认的PropertySourceFactory使用的就是DefaultPropertySourceFactory。当然,我们也可以自定义PropertySourceFactory,用于“生产”我们自定义的PropertySource。下面就演示一个将yaml文件解析成MapPropertySource的使用案列.
/**
* Spring中内置的解析yaml的处理器
* YamlProcessor
* - YamlMapFactoryBean --> 解析成Map
* - YamlPropertiesFactoryBean --> 解析成Properties
*/
public class YamlMapSourceFactory implements PropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
YamlMapFactoryBean yamlMapFactoryBean = new YamlMapFactoryBean();
yamlMapFactoryBean.setResources(resource.getResource());
Map<String, Object> map = yamlMapFactoryBean.getObject();
return new MapPropertySource(name, map);
}
}
// 加了factory属性,必须加name属性
// 有了factory机制,我们可以做很多自定一的扩展,比如配置可以从远程来
@PropertySource(name = "my.yaml",value = "classpath:/my.yaml",encoding = "UTF8",factory = YamlMapSourceFactory.class)
public static class PropertyConfig {
}
到这边我们对@PropertySource已经有了一个感性的认识,知道了其主要作用是将各种类型的外部化配置文件以key-value的形式加载到Spring的Environment中。这个部分我们从源码的角度来分析下Spring是怎么处理@PropertySource这个注解的。分析源码可以加深我们对@PropertySource的认识(看源码不是目的,是为了加深理解,学习Spring的设计思想).
@PropertySource注解的处理是在ConfigurationClassPostProcessor中进行触发的。最终会调用到ConfigurationClassParser的processPropertySource方法.
// ConfigurationClassParser#processPropertySource
private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
String name = propertySource.getString("name");
if (!StringUtils.hasLength(name)) {
name = null;
}
String encoding = propertySource.getString("encoding");
if (!StringUtils.hasLength(encoding)) {
encoding = null;
}
String[] locations = propertySource.getStringArray("value");
Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");
Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
// 如果有自定义工厂就使用自定义工厂,没有自定义工厂就使用DefaultPropertySourceFactory
PropertySourceFactory factory = (factoryClass == PropertySourceFactory.class ?
DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiateClass(factoryClass));
// 遍历各个location地址
for (String location : locations) {
try {
// location地址支持占位符的形式
String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
// 获取Resource
Resource resource = this.resourceLoader.getResource(resolvedLocation);
addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
}
catch (IllegalArgumentException | FileNotFoundException | UnknownHostException | SocketException ex) {
// Placeholders not resolvable or resource not found when trying to open it
if (ignoreResourceNotFound) {
if (logger.isInfoEnabled()) {
logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
}
}
else {
throw ex;
}
}
}
}
总的来说,Spring处理@PropertySource的源代码非常简单,这边就不再过多赘述了.
最后此篇关于Spring注解系列——@PropertySource的文章就讲到这里了,如果你想了解更多关于Spring注解系列——@PropertySource的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
在Spring框架中@PropertySource注解是非常常用的一个注解,其主要作用是将外部化配置解析成key-value键值对"存入"Spring容器的Environment
我想使用 @PropertySource 注释设置动态属性源值。谁能告诉我如何实现这一目标?对于下面我动态传递属性文件名。 @Configuration @PropertySource("classp
为什么当我尝试从属性文件输出数据时,显示的数据是错误的? 在我的 ChatApp 项目中,我有 datasource-cfg.properties 文件: # DataSource ds.databa
我有一个@Configuration类。这个类有一个@PropertySource。 我希望每个应用程序都有一个不同的属性。 示例: @Configuration @PropertySource("f
我有一个完美的测试设置,如下所示...... @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(loader = Annota
自 4.0 以来, Spring 为所有标记为 @Configuration 的类引入了一个新的注解 @PropertySources。它采用不同的 @PropertySource 作为参数。 @Pr
我正在使用 Spring Java 配置来创建我的 bean。但是这个 bean 对 2 个应用程序是通用的。两者都有一个属性文件 abc.properties 但具有不同的类路径位置。当我把明确的类
在我的 sprint 启动应用程序中,我有一个配置类来读取属性文件:common.properties 和 dev.properties。我在两个属性文件中都有相同的 key server.url。该
我正在 Tomcat 中将 Spring Boot 应用程序部署为 WAR 文件。我希望我的 application-local.properties 能够覆盖 application.propert
我的配置文件有问题,它位于我的 jar 文件之外的其他目录中。 我使用 @PropertySource 加载属性。 @PropertySource(ignoreResourceNotFound = t
我只需要读取MyServiceImpl.java类中的menu.properties文件这些值不是特定于环境的。 menu.properties ---------------- menu.optio
我有一个 micronaut 项目,我想为私有(private)数据(如数据库连接等)提供一个非版本化的配置文件 此信息必须通过@Property注释加载,但由于将有多个.yml(至少还有一个appl
我有一个关于以编程方式向 Spring 上下文添加属性的问题。 GenericXmlApplicationContext ctx = new GenericXmlApplicationContext(
我正在尝试通过以下方式创建一个 spring 配置类 @Configuration @PropertySource(value={"file:${my.dir}/fileone.properties"
嗨,我是 Spring 和 Jpa 集成的初学者。当我尝试配置我的数据库连接时,详细信息处理程序 itp。我发现了 Spring 的奇怪行为。 首先,我有3个配置文件: 1) RootConfig -
如何在 spring 中刷新 @PropertySouce(propertyFile)。 例如:-属性文件中有一个参数:- MY_APP_NAME=MY APPLICATION 我正在使用
我想用 java ... -Denv=prod ... 启动我的程序并且有 @PropertySource("classpath:/settings/$idontknowwhat$/database.
配置 @Configuration @PropertySources({ @PropertySource("classpath*:properties/test-database.proper
我遇到了连线问题,但没有找到任何提示。 我正在使用属性文件处理数据库分片配置。我得到了一个负责加载这些属性的类: @Component @PropertySources(value = *arrayO
无论如何我可以在我的程序中知道通过Spring的@PropertySource注释加载的文件的完整路径。我需要它显示在日志中,以便可以知道应用程序中正在使用哪个属性文件 最佳答案 此信息已由 Stan
我是一名优秀的程序员,十分优秀!