【问题标题】:How can I instantiate an injected class (using Spring) before logback configuration如何在 logback 配置之前实例化注入的类(使用 Spring)
【发布时间】:2012-07-10 22:13:27
【问题描述】:

我正在使用 spring 将一个类注入到我的 PropertyDefiner 实现中,该类将用于帮助在 logback.xml 文件中设置一些属性(通过dynamic property loading)。

我很想在配置 logback 之前加载和实例化这个类。关于如何做到这一点的任何想法?

【问题讨论】:

    标签: spring configuration logback applicationcontext


    【解决方案1】:

    如果你在 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 来实现

    【讨论】:

    • 使用 \@component 和 \@Autowired 注释对我不起作用。也没有实现 ApplicationContextAware 来获取应用程序上下文。在我需要进行此调用时,应用程序上下文似乎尚未初始化。
    【解决方案2】:

    我不知道目前(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()

    【讨论】:

    • 这里的问题似乎是“以某种方式获取 spring 应用程序上下文”这一行。这就是我发布的替代解决方案的障碍。
    【解决方案3】:

    我的解决方案导致没有实现 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 的其他应用程序中,但可能具有不同的属性。这些属性是从数据库中提取的,也可能因环境而异。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-05
      • 2017-05-17
      • 1970-01-01
      • 1970-01-01
      • 2011-12-20
      相关资源
      最近更新 更多