用 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 值提供给我们的独立应用程序需要一个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系统正确初始化