在 Spring Boot 加载自定义属性文件(@PropertySource注解)文章中,介绍了怎样使用 @PropertySource 注解加载自定义的属性文件,属性文件可以来自 classpath 或者本地文件(file)。
但是,最近有一个项目同时使用了 @PropertySource 和 @Configration 注解去加载自定义的属性文件,在 Bean 中可以使用 @Value 注解正常注入属性值,但在其他属性配置文件中不能使用 ${} 占位符解析自定义的属性。
为了解决上面存在的问题,本文我们将通过自定义实现 EnvironmentPostProcessor 接口来实现加载自定义的属性文件。
在 D 盘根目录下面创建 my.properties 文件,文件内容如下:
beanName2=TestBean(D:\)
同时,在项目的 resources 下面创建 application.properties 文件,内容如下:
beanName=[${beanName2}]
实现 EnvironmentPostProcessor 接口的 postProcessEnvironment() 方法,在该方法中将通过 Properties 类加载 D:\my.properties 属性文件,然后将属性文件的内容添加 Spring 的环境中(ConfigurableEnvironment)。Java 代码如下:
package com.hxstrive.hello_world.customer; import org.springframework.boot.SpringApplication; import org.springframework.boot.env.EnvironmentPostProcessor; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.PropertiesPropertySource; import java.io.File; import java.io.FileInputStream; import java.util.Properties; /** * 自定义 EnvironmentPostProcessor * @author hxstrive.com 2022/9/2 */ public class MyEnvironmentPostProcessor implements EnvironmentPostProcessor { @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { try { System.out.println("#### postProcessEnvironment()"); File proFile = new File("D:\\my.properties"); // 加载自定义的属性 Properties properties = new Properties(); properties.load(new FileInputStream(proFile)); // 将属性文件添加到环境中 environment.getPropertySources().addFirst( new PropertiesPropertySource(proFile.getName(), properties)); } catch (Exception e) { e.printStackTrace(); } } }
在项目的 resources/META-INF 目录下面创建 spring.factories 文件,添加如下配置信息:
# 启用我们的自定义环境处理类 org.springframework.boot.env.EnvironmentPostProcessor=com.hxstrive.hello_world.customer.MyEnvironmentPostProcessor
创建一个配置类,通过 @Autowired 注入 Environment 对象,使用 env.getProperty("beanName") 获取指定属性的值,设置到 TestBean 中。代码如下:
package com.hxstrive.hello_world.config; import com.hxstrive.hello_world.entity.TestBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.core.env.Environment; /** * 测试验证 @PropertySource 注解 * @author hxstrive.com 2022/9/2 */ @Configuration public class AppConfig { @Autowired private Environment env; @Bean public TestBean testBean() { TestBean testBean = new TestBean(); testBean.setName(env.getProperty("beanName")); return testBean; } }
使用 @SpringBootTest 注解创建一个简单的测试类,如下:
package com.hxstrive.hello_world.config; import com.hxstrive.hello_world.entity.TestBean; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class AppConfigTest { @Autowired private TestBean testBean; @Test void contextLoads() { String name = testBean.getName(); System.out.println("name=" + name); } }
运行上面测试示例,控制台输出信息如下:
... #### postProcessEnvironment() . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.3.1.RELEASE) ... name=[TestBean(D:)]