2010-12-13 75 views
2

我正在使用Spring和slf4j的应用程序。该应用程序并行使用更多的ApplicationContext。 有没有办法让这些不同的ApplicationContexts使用不同的日志记录属性? 因此,第一个AC可以登录到“x.txt”,而第二个登录到“y.txt”。Spring:针对不同ApplicationContext的不同日志记录行为

我不想使用更多的属性文件。适当的方法是在Spring XML配置文件中定义一个Logger Bean,我可以在其中为相应的属性设置不同的输出目标。

例如:

<bean id="LoggerBean" class="???"> 
    <property name="target" value="${target}" /> 
</bean> 

在这里,我可以操纵来自源的目标变量,这将是非常方便的。

private static final Logger log = LoggerFactory.getLogger(MyClass.class); 

所以LoggerFactory.getLogger将使用LoggerBean bean的配置实例化一个记录器类。

我需要一个方法,其中每个ApplicationContext都有自己的LoggerFactory具有不同属性(如不同的目标输出)的对象。所以我不必重写当前的代码。

我使用ApplicationContexts由相同的xml配置文件配置。所以这些ApplicationContexts使用 相同的类。正因为如此,所有LoggerLoggerFactory实例化他们英寸 所有记录仪使用LoggerFactory.getLogger(MyClass.class)形式实例化的同一类的名称,因为这些类在所有ApplicationContext(“MyClass的”),我不能定义不同的名称Loggers相同。

感谢您的回复。

回答

2

最终溶液是下列:

SLF4J和支持的logback MDC其中包含每个线程的基础上的键/值对。虽然我们的问题的主要优点是子线程会自动继承其父项的键/值对,因此如果在ApplicationContext初始化期间创建了新的线程,该线程将从调用线程继承这些线对。之后,您可以将这些存储的值包含在日志消息模式中。 因此,我在加载ApplicationContext之前在MDC中放置了一个特殊的ApplicationContext标识符。当类使用Logger字段实例化时,这些字段将获得日志消息模式中包含的唯一标识符。

<Pattern>[%X{contextID}] - [%thread] - %date{dd/MM/yyyy HH:mm:ss} %level %msg%n</Pattern> 

LoggerSeparator.java

public class LoggerSeparator implements InitializingBean{ 
    private Integer contextID; 

    public LoggerSeparator() {} 

    public void setContextID(int id) { 
     this.contextID = id; 
    } 

    @Override 
    public void afterPropertiesSet() throws Exception { 
     if (contextID != null) 
      MDC.put("contextID", contextID.toString()); 
    } 
} 

这个bean是第一次在main.xml中定义的Spring bean。

<bean class="com.myproblem.LoggerSeparator"> 
    <property name="contextID" value="${contextID}" /> 
</bean> 
... 

该类在MD中设置contextID。 contextID来自源代码。

... 
Properties props = new Properties(); 
props.put("contextID", contextID); 
PropertyPlaceholderConfigurer conf = new PropertyPlaceholderConfigurer(); 
conf.setProperties(props); 
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(); 
context.addBeanFactoryPostProcessor(conf); 
context.setConfigLocation("beans/main.xml"); 
context.refresh(); 
... 

日志消息被记录到一个文件中,但现在我可以通过它们的唯一标识符将它们分开。

1

您可以使用自定义FactoryBean的记录添加到右键:

public class Slf4jLoggerFactoryBean implements FactoryBean<Logger> { 

    private String loggerName; 

    public Logger getObject() throws Exception { 
     return LoggerFactory.getLogger(loggerName); 
    } 

    public Class<?> getObjectType() { 
     return Logger.class; 
    } 

    public boolean isSingleton() { 
     return true; 
    } 

    public void setLoggerName(String loggerName) { 
     this.loggerName = loggerName; 
    } 

} 

然后是XML将看起来像:

<bean id="LoggerBean" class="com.example.Slf4jLoggerFactoryBean"> 
    <property name="target" value="${target}" /> 
</bean> 
+0

private static final Logger log = LoggerFactory.getLogger(MyClass.class); 这里org.slf4j.LoggerFactory的静态方法会生成一个org.slf4j.Logger类。 我需要一个方法,其中每个ApplicationContext都有一个具有不同属性的LoggerFactory对象(如不同的目标输出)。 因此,我不必重写当前的代码,只需将导入语句交换到我的LoggerFactory实现。 – Sharp 2010-12-13 15:34:18

+0

更改FactoryBean返回SLF4J记录器 – 2010-12-14 09:57:06

4

您可以定义一个Spring管理的bean,将配置记录器。例如,假设你使用的logback实现SLF4J API,春季设置其属性之后,这个类将加载指定的日志记录配置文件导入的logback:

public class LogBackConfigurer implements InitializingBean { 
    private Resource location; 

    public void setLocation(Resource location) { 
     this.location = location; 
    } 

    public void afterPropertiesSet() throws Exception { 
     JoranConfigurator configurator = new JoranConfigurator(); 
     LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); 
     configurator.setContext(loggerContext); 
     configurator.doConfigure(location.getInputStream()); 
    } 
} 

在每个Spring配置文件,你想有一个不同的日志记录配置中,使用不同的日志记录配置文件位置来定义类似以下的bean。

<bean class="com.example.log.LogBackConfigurer"> 
    <property name="location" value="classpath:a-logback.xml"/> 
</bean> 

类修改单一应用程序的日志记录情况下,因为你要拨打的静态记录仪工厂方法在应用程序代码是必要的。为确保日志记录配置文件不会彼此分开,它们都必须定义不同名称的记录器。

+0

感谢您的回复。这对我来说是非常有用的。 但还有一些额外的问题。 我使用由同一个xml配置文件配置的ApplicationContexts。所以这些ApplicationContexts使用 相同的类。因此,所有Logger都从LoggerFactory实例化而来,它们使用相同的类名。 所有Logger都由“LoggerFactory.getLogger(MyClass.class)”形式实例化,因为这些类在所有ApplicationContext(“MyClass”)中都是相同的,我无法定义不同名称的记录器。 – Sharp 2010-12-15 08:34:37

相关问题