2010-12-13 2 views
2

Я работаю над приложением, использующим Spring и slf4j. Это приложение использует больше ApplicationContext параллельно. Есть ли какой-либо способ для этих различных ApplicationContexts использовать разные свойства журналирования? Итак, первый AC может войти в «x.txt», а второй - в «y.txt».Spring: разные правила ведения журнала для разных приложений ApplicationContext

Я бы не хотел использовать больше файлов свойств. Соответствующим способом было бы определить файл конфигурации Logger Bean in Spring XML, в котором я мог бы установить другую цель вывода для соответствующего свойства.

Например:

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

Здесь я мог манипулировать целевой переменной от источника, который был бы очень кстати.

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

Так LoggerFactory.getLogger будет использовать конфигурацию LoggerBean боба, чтобы создать экземпляр класса Logger.

Мне нужен метод, в котором каждый ApplicationContext имеет собственный объект LoggerFactory с различными свойствами (например, с другим целевым выходом). Поэтому мне не пришлось бы переписывать текущий код.

Я использую ApplicationContexts, настроенный тем же конфигурационным файлом xml. Таким образом, эти ApplicationContexts используют те же классы. Из-за этого все Logger создаются от LoggerFactory с теми же именами классов, в которых они использовались. Все регистраторы создаются по LoggerFactory.getLogger(MyClass.class) формам, так как эти классы одинаковы во всех ApplicationContext («MyClass»), я не могу определить по-другому Loggers ,

Спасибо за любой ответ.

ответ

2

Окончательное решение было следующее:

SLF4J и Logback поддержка MDC, которая содержит пары ключ/значение на основе каждого потока.Хотя главными преимуществами нашей проблемы является то, что дочерний поток автоматически наследует пары ключ/значение своего родителя, поэтому, если во время инициализации ApplicationContext создается новый поток, этот Thread наследует эти пары из вызывающего потока. После этого вы можете включить эти сохраненные значения в шаблон журнала сообщений. Итак, я поместил специальный идентификатор 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()); 
    } 
} 

Этот компонент является первым определен Spring Bean в main.xml.

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

Этот класс задает контекстный идентификатор в MD. Контекстный идентификатор исходит из исходного кода.

... 
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

приватный статический конечный журнал регистрации Log = LoggerFactory.getLogger (MyClass.class); Здесь статический метод org.slf4j.LoggerFactory генерирует класс org.slf4j.Logger. Мне нужен метод, в котором каждый ApplicationContext имеет собственный объект LoggerFactory с различными свойствами (например, с другим целевым выходом). Поэтому мне не пришлось бы переписывать текущий код, просто поменяйте операторы импорта на мою реализацию LoggerFactory. – Sharp

+0

Изменен FactoryBean, чтобы вернуть регистратор SLF4J –

4

Вы можете определить Spring-управляемый компонент, который будет настроить регистратор. Например, если вы используете Logback реализовать SLF4J API, этот класс будет загружать указанный конфигурационный файл журналирования в Logback после 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()); 
    } 
} 

В каждом файле конфигурации Spring вы хотите иметь различные протоколирования конфигурации, определите компонент, похожий на следующий, с другим местоположением файла конфигурации журнала.

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

Класс изменяет единый контекст протоколирования приложения шириной, которая необходима, потому что вы хотите, чтобы вызвать статический метод Logger фабрики в коде приложения. Чтобы файлы конфигурации ведения журнала не наступали друг на друга, каждый из них должен определять разные имена журналов.

+0

Спасибо за ваш ответ. Это было очень полезно для меня. Но есть некоторые дополнительные проблемы. Я использую ApplicationContexts, настроенные одним и тем же конфигурационным файлом xml. Таким образом, эти ApplicationContexts используют те же классы. Из-за этого все Logger создаются из LoggerFactory с теми же именами классов, в которых они использовались. Все регистраторы создаются с помощью формы «LoggerFactory.getLogger (MyClass.class)», поскольку эти классы одинаковы во всех ApplicationContext («MyClass») , Я не могу определить иначе названные Loggers. – Sharp

Смежные вопросы