4

我目前的构建负责人在理论上有一个好主意 - 构建一个自定义 Log4J 附加程序,该附加程序接受 Spring 管理的 bean 并使用它们将错误记录到各种其他来源,而不仅仅是标准日志文件。然而,除了创建一个在启动时使用应用程序上下文初始化的单例(代码稍后),我似乎想不出在 Log4J appender 中检索 Spring 托管 bean 的任何其他选项。

public class SpringSingleton implements ApplicationContextAware {
    private static ApplicationContext context;
    public SpringSingleton() {
        super();
    }
    public static ApplicationContext getContext() {
        return SpringSingleton.context;
    }
    public void setApplicationContext(ApplicationContext context) {
        if(SpringSingleton.context != null) {
            throw new IllegalStateException("Context is already set!");
        }
        SpringSingleton.context = context;
    }
}

理想情况下,这些属性可以像 Spring 中的 bean 一样通过依赖注入来设置——bean 引用永远不会改变,无论有多少 appender 被初始化。有任何想法吗?

4

2 回答 2

7

由于 log4j 必须在Spring之前初始化,因此您将遇到 boostrap 问题。无论您使用的是自定义配置还是 Log4j 的标准初始化程序,它都必须在应用程序上下文之前启动。

现在,您理论上可以让您的自定义附加程序“懒惰地”初始化自己(通过您上面建议的方法或通过使附加程序本身成为“半”单例 - 例如附加程序类具有由afterPropertiesSet()方法填充的静态实例字段;那样您可以在 Spring 中将 appender 本身创建为 bean),但它看起来有些混乱和不一致。

另一种方法是在 Spring 上下文初始化后动态重新配置 Log4j;例如,编写一个侦听器来捕获 a ContextStartedEvent,从上下文中获取所有类型的 beanAppender并将它们添加到 Log4j 配置中。这也将允许您将附加程序创建为 bean,但在一定程度上避免单例混乱。

于 2009-11-13T18:06:40.357 回答
0

有点晚了,但我希望这可以帮助别人。我在以下链接中提供的答案中记录了此问题的解决方案:

log4j - 从日志记录 appender 类访问 spring bean

于 2015-06-02T00:07:44.427 回答