【问题标题】:Spring: Make sure a particular bean gets initialized firstSpring:确保首先初始化特定的bean
【发布时间】:2011-10-23 18:49:49
【问题描述】:

我有一个库在运行时设置和配置 log4j(没有 log4j.properties 或 log4j.xml)。我已经定义了一个名为 MyLoggerFactory 的 bean,我希望这是第一个使用 spring 初始化的 bean。我已经看到一个问题已经提交给 spring 以支持初始化顺序,但我想知道是否有办法将 bean 标记为第一个由 spring 容器初始化的 bean?

【问题讨论】:

  • 无论如何,您可能都希望包含 log4j.properties,至少对于 Spring 启动 - 在 Spring 初始化您的日志记录 bean 之前,它将使用其内部日志记录的默认值,通常,如果您重新使用 Log4J,这将是类路径上定义的 log4j.properties 文件。该文件不必非常复杂 - 通常它可以简单地输出到控制台,因为如果应用程序成功启动,有意义的日志记录将通过您的自定义 bean。

标签: java spring


【解决方案1】:

您的选择是:

  1. 使用@DependsOn注解(spring 3.0.x后可用)或depends-onxml-attribute,让所有使用配置的loggers的类都依赖于logger factory
  2. 使工厂成为记录器的实际工厂,并将记录器注入 bean,而不是直接调用工厂 - 这与选项 1 基本相同,只是隐含了依赖关系。这是我推荐的选项。
  3. 将初始化代码移动到指定调用顺序的代码部分——main() 方法,或在初始化 Spring 之前注册的 ServletContextListener

没有办法在 Spring 中明确定义初始化顺序,而且很可能永远不会——考虑到您可以加载许多可能具有冲突顺序的应用程序上下文配置文件,因此无法为它定义有用的语义。我还没有看到通过重构代码以更好地符合依赖注入模式而无法实现所需排序的情况。

【讨论】:

  • 我有点实现第三个选项,但这意味着我首先在 spring 之外显式地初始化记录器。我的偏好是大部分对象的生命周期由 spring 管理,但我理解你的观点,一个好的设计模式应该能够处理它。
  • @Prasanna 如果您希望大部分对象都由 Spring 管理,那么您绝对应该在 Spring 中管理记录器,或者将记录器创建封装在记录器工厂中并将其注入其他类.如果您想支持使用 LogManager 静态方法检索记录器,那么您将不得不使用选项 3——因为 LogManager 是一个(专门的)对象工厂,不能由 Spring 合理管理。
  • @Inerida,是的,LogManager 是问题所在,除了 3,我没有看到任何其他选项,
  • @prayagupd - 你是我们所有人的英雄,所以你的努力会更好。反正你不需要我的许可,我想问会降低我到家时忘记它的风险
【解决方案2】:

您可以在主@Configuration 中@Autowired 一个@Configuration

@Configuration
@Import(BusinessConfig.class, EarlyBeans.class)
public class MainConfiguration {

    // The bean defined in EarlyBean will be loaded before 
    // most beans references by MainConfiguration, 
    // including those coming from BusinessConfig
    @Autowired
    EarlyBeans earlyBeans;

}

@Configuration
public class EarlyBeans {
    @Bean
    public Void earlyBean(ApplicationContext appContext) {
        // .getBeansOfType allows to call for beans which might not exist
        appContext.getBeansOfType(TechnicalBean.class);

        return null;
    }

}

【讨论】:

  • 非常有用,只有 1 条评论 - @Import(EarlyBeans.class) 或 @Autowired EarlyBeans earlyBeans 之一;足以让它发挥作用。
  • 很抱歉对一个老问题发表评论 - 这与调用 appContext.getBeansOfType(TechnicalBean.class) 或在 MainConfiguration 本身中使用 @Autowired TechnicalBean 有何不同?
【解决方案3】:

这是一项请求但尚未解决的功能。您可以使用depends-on,但过于冗长。关注 tis 链接以获取更多信息: https://jira.springsource.org/browse/SPR-3948

【讨论】:

    【解决方案4】:

    您可以将应用程序上下文拆分为多个,并在主应用程序上下文中使用导入。可以将主要环境设置按导入顺序放在首位,然后继续添加其他文件。

    可能如下所示。

    <!-- Import environment properties settings. -->
    <import resource="Spring-Env.xml"/>
    <!-- Import All the other Application contexts. -->
    <import resource="Spring-MainApplicationContext.xml"/>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-23
      • 1970-01-01
      • 2023-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多