2010-12-13 10 views
2

私はSpringとslf4jを使用するアプリケーションで作業しています。そのアプリケーションは、より多くのApplicationContextを並列に使用します。 これらの異なるApplicationContextが異なるログプロパティを使用する方法はありますか? 最初のACは "x.txt"に、2番目のACは "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はLoggerクラスをインスタンス化するLoggerBean Bean構成を使用します。

私は、それぞれのApplicationContextが異なるプロパティ(異なるターゲット出力のような)を持つ独自のLoggerFactoryオブジェクトを持つメソッドが必要です。だから私は現在のコードを書き直す必要はありません。

同じxml設定ファイルで設定されたApplicationContextsを使用します。したがって、これらのApplicationContextでは、同じクラスの が使用されます。そのため、すべてLoggerは、LoggerFactoryからインスタンス化されています。 すべてのLoggerは、すべてApplicationContext( "MyClass")で同じクラスなのでLoggerFactory.getLogger(MyClass.class)という形式でインスタンス化されますが、別の名前はLoggers

ご回答ありがとうございます。

あなたがコンテキストにロガーを追加するためのカスタム FactoryBeanを使用することができます

答えて

2

最終的な解決策は、以下の通りでした。私たちの問題の主な利点は、親スレッドのキーと値のペアを子スレッドが自動的に継承するためです。したがって、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スプリングビーン定義されます。

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

このクラスは、contextIDをMDに設定しました。 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つのファイルに記録されますが、これらのログメッセージは一意の識別子で分けることができます。

1

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

プライベートstatic final Logger log = LoggerFactory.getLogger(MyClass.class); ここで、org.slf4j.LoggerFactoryのstaticメソッドは、org.slf4j.Loggerクラスを生成します。 私は、各ApplicationContextが異なるプロパティ(異なるターゲット出力のような)を持つ独自のLoggerFactoryオブジェクトを持っているメソッドが必要です。 したがって、現在のコードを書き直す必要はなく、import文をLoggerFactory実装に入れ替えるだけです。 – Sharp

+0

FactoryBeanをSLF4Jロガーを返すように変更しました –

4

あなたが設定されますSpring管理Beanを定義することができますロガー。各Spring構成ファイルで

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()); 
    } 
} 

あなたが別のログを持ちたい:春は、そのプロパティを設定した後、たとえば、あなたはSLF4J APIを実装するlogbackを使用していると仮定すると、このクラスはlogbackに指定されたロギングの設定ファイルをロードします次のような別のロギング設定ファイルの場所でBeanを定義します。

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

クラスは、アプリケーションコードで静的なLoggerファクトリメソッドを呼び出すために必要な、アプリケーション全体の単一のロギングコンテキストを変更します。ロギング設定ファイルが互いの上に乗っていないようにするには、それぞれ異なる名前のロガーを定義する必要があります。スレッドごとにキー/値のペアが含まれている

SLF4JとLogbackサポートMDC

+0

返信いただきありがとうございます。それは私のために非常に便利でした。 しかし、いくつかの問題があります。 同じxml設定ファイルで設定されたApplicationContextを使用します。したがって、これらのApplicationContextでは、同じクラスの が使用されます。そのため、すべてのLoggerは、使用されているのと同じクラス名でLoggerFactoryからインスタンス化されます。 すべてのLoggerはすべてのApplicationContext( "MyClass")で同じであるため、LoggerFactory.getLogger(MyClass.class) 、私は異なった名前のロガーを定義することはできません。 – Sharp

関連する問題