如何让log4j2读取Maven指定的外部application.properties配置属性
类路径下存放标准log4j2配置与Spring属性文件application.properties。log4j2.xml配置片段:
<Properties> ... <Property name="APP_LOG_ROOT">${bundle:application:log.root.dir}</Property> ... </Properties>
类路径内置application.properties配置片段:
... log.root.dir=/opt/tomcat/logs ...
默认场景下log4j2.xml可正常读取配置属性,但使用Maven构建制品、指定替换的外部application.properties文件时:
mvn clean install -Dapplication.properties.path=file:/some_path/application.properties
构建完成后Spring可正常读取新配置文件中的属性:
@Value("${log.root.dir}") private String ololo;
但log4j2无法自动读取该外部配置文件中的对应属性。
${bundle:xxx:yyy}是log4j2原生的资源包查找语法,仅会从类路径下的资源文件加载属性,它和Spring的配置加载体系完全独立:
- log4j2初始化时机远早于Spring容器启动,不会感知Spring加载外部配置文件的逻辑
- 通过Maven参数指定的外部
application.properties不在类路径扫描范围内,log4j2默认无法定位到该文件
方案1:启动时指定log4j2额外扫描的属性文件(适合log4j2 2.10+版本)
应用启动时增加JVM参数,直接把外部properties文件路径传给log4j2,不需要修改原有log4j2.xml的配置写法:-Dlog4j2.bundle.resource.file.path=/some_path/application.propertieslog4j2会自动把该路径下的属性文件纳入bundle查找范围,和读取类路径下的配置文件逻辑一致。
方案2:使用log4j2的Spring适配模块(推荐,Spring生态下无兼容问题)
引入log4j2针对Spring的适配依赖,替换原生log4j2-core的普通依赖,将log4j2配置文件重命名为log4j2-spring.xml,避免log4j2提前初始化。
把原有占位符写法从${bundle:application:log.root.dir}改成${spring:log.root.dir}即可。这种写法会直接从Spring的Environment上下文读取属性,无论application.properties是类路径内置、外部指定还是来自配置中心,只要Spring能加载到的属性,log4j2都能同步读取,完全对齐Spring的配置加载规则。方案3:构建阶段直接注入属性值(适合部署路径构建时固定的场景)
借助maven-resources-plugin,在构建打包阶段直接读取指定的外部application.properties,把log.root.dir的值替换到log4j2.xml的占位符中,不需要运行时再做属性查找。插件配置参考:<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>3.3.1</version> <executions> <execution> <id>filter-log4j2-config</id> <phase>process-resources</phase> <goals> <goal>copy-resources</goal> </goals> <configuration> <outputDirectory>${project.build.outputDirectory}</outputDirectory> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>log4j2.xml</include> </includes> <filtering>true</filtering> <filters> <filter>${application.properties.path}</filter> </filters> </resource> </resources> </configuration> </execution> </executions> </plugin>方案4:自定义log4j2属性查找插件(灵活度最高)
实现log4j2的StrLookup接口,编写自定义属性查找逻辑,主动加载指定路径的外部properties文件,添加@Plugin注解注册到log4j2后,就可以用自定义前缀的占位符读取外部属性,比如${extConfig:log.root.dir},适合有特殊定制需求的场景。
内容的提问来源于stack exchange,提问作者Andrew Samsonov

