Spring Конфигурация загрузочного программного обеспечения

Как настроить регистрацию программно в загрузочном приложении spring?

Использование файла xml или properties недостаточно гибко для моих нужд.

Обновление: Я хочу добиться чего-то вроде этого:

@Value("${logging.level.root}")
private String loggingLevelRoot;

@Value("${logging.level.myApp}")
private String loggingLevelMyApp;

@Value("${logging.file}")
private boolean fileAppenderEnabled;

....

setLevel(Logger.ROOT_LOGGER_NAME, Level.toLevel(loggingLevelRoot)));
setLevel("com.myapp", Level.toLevel(loggingLevelMyApp)));
setLevel("org.springframework", Level.WARN);
setLevel("org.apache.coyote", Level.INFO);
setLevel("org.apache.catalina", Level.INFO);
setLevel("org.apache.catalina.startup.DigesterFactory", Level.ERROR);
setLevel("org.apache.catalina.util.LifecycleMBeanBase", Level.ERROR);

Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
logger.addAppender(createConsoleAppender());
if (fileAppenderEnabled) {
    logger.addAppender(createFileAppender());
}

Все, что у меня есть для среды:

  • logging.level.root = [INFO, DEBUG,..]
  • logging.level.myApp = [INFO, DEBUG,..]
  • logging.file = [true | ложь]

Нет дублирования XML, Groovy и других форматов, с которыми я действительно не хочу иметь дело.

В конце концов, это действительно касается достижения такой же гибкости для ведения журнала, как spring JavaConfig для beans. XML или другие форматы файлов просто слишком статичны, требуют слишком большого дублирования и недостаточно хорошо интегрируются с остальной конфигурацией приложения.

Почему журнал должен быть настроен иначе, чем любой другой bean или сервис? Это не имеет смысла.

Ответ 1

Я не уверен, что вам нужно или нужно отключить стандартную XML-конфигурацию системы ведения журнала, но вы хотите выполнить свои настройки после того, как это было сделано. К счастью, это довольно легко, как это сделано как можно раньше в цепочке инициализации для SpringApplication. Простейшим местом для размещения кода, вероятно, является SpringApplicationInitializer (он должен реализовать ApplicationContextInitializer, чтобы его можно было добавить в SpringApplication). Например.

SpringApplication application = new SpringApplication(MySources.class);
application.addInitializers(new LoggingInitializer());
application.run(args);

Вы не сможете сделать инъекцию зависимостей в инициализатор, если вы сделаете это именно так, но это гарантирует, что он будет вызван как можно раньше на жизненном цикле. Если ваш инициализатор реализует EnvironmentAware, вам также будет передан экземпляр Environment перед вызовом SpringApplicationInitializer.initialize() - с помощью которого вы можете разрешить компоненты, зависящие от среды, в вашем примере, например.

String loggingLevelRoot = environment.getProperty("logging.level.root");

Как только вы его заработаете, чтобы избежать необходимости делать то же самое для всех приложений, вы можете сделать его декларативным, добавив META-INF/spring.factories, содержащий ваш класс инициализатора:

org.springframework.context.ApplicationContextInitializer=\
my.pkg.for.LoggingInitializer

Если вам действительно нужна инъекция зависимостей и разрешение @Value, я думаю, вам нужно будет признать, что ApplicationContext будет полностью обновлен, прежде чем вы сможете настроить что-либо. Если это приемлемый компромисс, я рекомендую просто добавить LoggingInitializer к вашему контексту и реализовать его CommandLineRunner.