问题描述
我有一个配置属性类,我想将其注入到自定义 log4j2 RewritePolicy 中。 例如
@Plugin(name = "MyPolicy",category = "Core",elementType = "rewritePolicy",printObject = true)
public class MyPolicy implements RewritePolicy {
private MyPolicyProperties myPolicyProperties; // <-- want to inject/autowire this
public MyPolicy() {}
@PluginFactory
public static MyPolicy createPolicy() {
return new MyPolicy();
}
@Override
public LogEvent rewrite(LogEvent logEvent) {
// do something with myPolicyProperties here
return Log4jLogEvent.newBuilder()
.setLoggerName(logEvent.getLoggerName())
.setMarker(logEvent.getMarker())
.setLoggerFqcn(logEvent.getLoggerFqcn())
// ... etc
.build();
}
}
@ConfigurationProperties("app.mypolicy")
@Getter
@Setter
public class MyPolicyProperties {
private String property1;
private int property2;
// ... etc
}
我已尝试实现 ApplicationListener
以按照 here 所述重新配置 log4j,但似乎无法配置 appender 和/或 rewritepolicy。还尝试实施 ApplicationContextAware
描述的 here 但也没有奏效。
是否可以访问 MyPolicyProperties
中的 MyPolicy
?
解决方法
它可以做到,但它几乎从不漂亮。这是因为 Log4j Plugins 是由 Log4j 的插件系统加载的,而 Spring Beans 是由 Spring 加载的。此外,它们不会同时被实例化。
如果您正在使用 Spring Boot,那么首先会发生的是 Log4j2 初始化,因为 SpringApplication 请求一个 Logger。因此,此时无法解析 Spring Bean,因为它不存在。稍后,Spring 的引导过程将再次初始化 Log4j,然后在应用程序设置期间它会再初始化一次或两次。在这些后续初始化期间,bean 可能可用。
根据您使用的应用程序类型,您可以找到 Spring 的 ApplicationContext,以便您可以调用 getBean() 并注入它。
没有通过注释或类似方法自动执行此操作的方法。
最简单的方法是在目标类中添加一个静态方法,该方法在 Spring 初始化时被初始化为引用自身,或者创建另一个类,该方法初始化静态方法以引用 Spring 创建的 bean。所以Spring会导致这些静态方法引用它创建的bean。然后让您的 Log4j 插件调用该静态方法以获取 bean 引用。一旦它不为空,您就可以将其保存在插件中,之后它应该可以正常运行。