【发布时间】:2012-07-10 22:13:27
【问题描述】:
我正在使用 spring 将一个类注入到我的 PropertyDefiner 实现中,该类将用于帮助在 logback.xml 文件中设置一些属性(通过dynamic property loading)。
我很想在配置 logback 之前加载和实例化这个类。关于如何做到这一点的任何想法?
【问题讨论】:
标签: spring configuration logback applicationcontext
我正在使用 spring 将一个类注入到我的 PropertyDefiner 实现中,该类将用于帮助在 logback.xml 文件中设置一些属性(通过dynamic property loading)。
我很想在配置 logback 之前加载和实例化这个类。关于如何做到这一点的任何想法?
【问题讨论】:
标签: spring configuration logback applicationcontext
如果你在 Spring 中使用注解,通过将要注入的类(即依赖项)标记为 @Component 然后在 PropertyDefiner 实现中使用 @Autowired 会很方便。这确保了第一个类将首先被实例化。 http://static.springsource.org/spring/docs/3.0.0.M3/spring-framework-reference/html/ch04s12.html
您需要的任何其他初始化都可以使用实例初始化程序块 http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html 来实现
【讨论】:
我不知道目前(2012-07)这是否可以优雅地完成。但是,LOGBACK-719 已请求支持注入。
如果您的 bean 工厂实现 AutowireCapableBeanFactory,给定 Spring Applicaton 上下文,您可以调用 autowireBean(Object existingBean) 来自动装配 bean。这是一个暂定的实现:
class Your.PropertyDefiner implements PropertyDefiner, LifeCycle {
@Autowired
@Qualifier("myKey")
String myKey;
public void start() {
ApplicationContext appContext = ... somehow get the spring app context
AutowireCapableBeanFactory factory = appContext.getAutowireCapableBeanFactory();
factory.autowireBean(this); // declare victory
}
}
仅当您的 PropertyDefiner 实现 LifeCycle 接口时,才会调用 start() 方法。此外,您需要 logback 版本 1.0.7 或更高版本。早期版本不调用start()。
【讨论】:
我的解决方案导致没有实现 PropertyDefiner。最初的问题变成了没有来自 spring 的应用程序上下文来设置动态属性的问题。我不确定为什么,但是在应用程序上下文可用之前,稍后的侦听器(在 Spring 侦听器之后)中的代码会被调用(调用 LoggerFactory 调用)。我尝试了很多方法,直到我开始寻找不同的方法。
我创建了一个侦听器(在服务器启动时调用)而不是使用动态属性,然后它以编程方式使用我想要的属性设置我的附加程序(通过 createAdminNotifyAppender)。
@Override
public void contextInitialized(ServletContextEvent arg0)
{
//Set up the property reader to pull the correct properties
ServletContext context = arg0.getServletContext();
ApplicationContext appContext = WebApplicationContextUtils.getWebApplicationContext(context);
propReader = (AppConfigPropertiesReader)appContext.getBean("propertySourcesPlaceholder");
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
createAdminNotifyAppender(lc, propReader);
}
createAdminNotify 方法只是简单地设置一个 appender 并将其添加到日志记录上下文中。 (如果你真的感兴趣,可以在thread 上查看该方法的实现。
现在我有一个单独的模块化监听器,我可以将它添加到使用 logback 的其他应用程序中,但可能具有不同的属性。这些属性是从数据库中提取的,也可能因环境而异。
【讨论】: