2010-12-13 70 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

相關問題