用 Spring 初始化 Log4J?

Posted

技术标签:

【中文标题】用 Spring 初始化 Log4J?【英文标题】:Initializing Log4J with Spring? 【发布时间】:2011-05-22 23:36:21 【问题描述】:

我有一个 Web 应用程序,它使用 Spring 的 Log4jConfigurer 类来初始化我的 Log4J 日志工厂。基本上,它使用不在类路径中的配置文件初始化 Log4J。

这里是配置:

<bean id="log4jInitializer" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" depends-on="sbeHome">
    <property name="targetClass" value="org.springframework.util.Log4jConfigurer" />
    <property name="targetMethod" value="initLogging" />
    <property name="arguments">
        <list>
            <value># MyAppHome + '/conf/log4j.xml'</value>
        </list>
    </property>
</bean>

但是我在应用程序启动时收到此错误:

log4j:WARN No appenders could be found for logger

大量 Spring 应用程序上下文初始化消息被打印到控制台。我认为这是因为 Spring 在有机会初始化我的记录器之前正在初始化我的应用程序。万一这很重要,我在 Log4J 之上使用 SLF4J。

有什么方法可以让我的 Log4jConfigurer 成为第一个初始化的 bean?还是有其他方法可以解决这个问题?

【问题讨论】:

【参考方案1】:

您可以在 web.xml 而不是 spring-context.xml 中配置 Log4j 侦听器

<context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>/WEB-INF/classes/log4j.web.properties</param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

所以它在春天开始之前就起来了。

【讨论】:

我应该提到我的 log4J 属性文件的路径来自一个 JNDI 字符串。如何将该 JNDI 值提供给 。如果我能做到这一点,我想我已经准备好了。 我发现了这个:coderanch.com/t/362833/Servlets/java/log-ServletContextListener——它展示了如何实现你自己的 log4j 配置监听器,它通过 JNDI 获取一些信息 我像他们一样创建了自己的 servlet 上下文侦听器,并且一切正常。谢谢。【参考方案2】:

我们的独立应用程序需要一个SMTPAppender,其中电子邮件配置已经存在于spring 配置文件中,我们不希望它在log4j.properties 中重复。

我将以下内容放在一起使用 spring 添加一个额外的附加程序。

<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetObject">
        <bean factory-method="getRootLogger"
              class="org.apache.log4j.Logger" />
    </property>
    <property name="targetMethod">
        <value>addAppender</value>
    </property>
    <property name="arguments">
        <list>
            <bean init-method="activateOptions"
                  class="org.apache.log4j.net.SMTPAppender">
                <property name="SMTPHost" ref="mailServer" />
                <property name="from" ref="mailFrom" />
                <property name="to" ref="mailTo" />
                <property name="subject" ref="mailSubject" />
                <property value="10" name="bufferSize" />
                <property name="layout">
                    <bean class="org.apache.log4j.PatternLayout">
                        <constructor-arg>
                            <value>%d, [%5p] [%t] [%c] - %m%n</value>
                        </constructor-arg>
                    </bean>
                </property>
                <property name="threshold">
                    <bean class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"
                          id="org.apache.log4j.Priority.ERROR" />
                </property>
            </bean>
        </list>
    </property>
</bean>

我们在类路径中还有一个log4j.properties 文件,其中详细说明了我们的常规FileAppenders

我意识到这对于您的要求可能有点过分了 :)

【讨论】:

【参考方案3】:

与其在代码中自己配置 log4j,不如通过添加将 log4j 指向您的(自定义)配置文件的位置

-Dlog4j.configuration=.../conf/log4j.xml

到您服务器的启动属性?

更好的是,只需将 log4j.xml 移动到默认位置 - 在类路径上 - 并让 log4j 自动配置自己。

【讨论】:

我正在尝试将 log4j 文件保留在 WAR 之外,以便我们可以让客户根据需要轻松调整它以进行问题诊断。至于JVM属性,目前我们连启动脚本都没有。客户只需部署 WAR 文件即可。 在某些情况下我们应该在路径-Dlog4j.configuration=file:conf/log4j.properties添加“文件”前缀 @matt b 请澄清类路径序列扫描【参考方案4】:

您可以使用类路径而不是硬编码路径。它对我有用

<bean id="log4jInitializer" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" depends-on="sbeHome">
    <property name="targetClass" value="org.springframework.util.Log4jConfigurer" />
    <property name="targetMethod" value="initLogging" />
    <property name="arguments">
        <list>
            <value>classpath:/conf/log4j.xml</value>
        </list>
    </property>
</bean>

【讨论】:

是否可以在此解决方案中使用 URL?【参考方案5】:

如果您使用 Jetty,您可以为每个应用程序添加额外的类路径:

http://wiki.eclipse.org/Jetty/Reference/Jetty_Classloading#Adding_Extra_Classpaths_to_Jetty

这将允许您以标准方式加载 log4 属性(从类路径:)

在 web.xml 中:

       <listener>
           <listener-class>org.springframework.web.util.Log4jWebConfigurer</listener-class>
       </listener>
       <context-param>
           <param-name>log4jConfigLocation</param-name>
           <param-value>classpath:$project.artifactId-log4j.properties</param-value>
       </context-param>

在 jetty-web.xml 中:

        <Set name="extraClasspath">
            <SystemProperty name="config.home" default="."/>/contexts/log4j
        </Set>

【讨论】:

以上是关于用 Spring 初始化 Log4J?的主要内容,如果未能解决你的问题,请参考以下文章

排除spring-boot-starter-web的Logback依赖关系会阻止log4j系统正确初始化

log4j2(一) 获取 ILoggerFactory

Spring的Log4J配置器Log4jWebConfigurer介绍

如何在java程序中手动初始化log4j.xml?

log4j在tomcat项目中的使用

log4j配置文件的手动加载与配置初始化