通过组件构造函数自动装配静态成员

时间:2012-12-18 19:33:18

标签: java spring static dependency-injection

我知道这个编译,但我的问题是,这是一个好主意吗?我很好奇为什么它可能不是一个好主意。更好的是,如果SomeStaticClass@Component,还有其他方法,但它也必须是MyComponent的静态成员。我的理解是它的设计很糟糕,让Spring自动装配静态成员。根据我所读到的,我仍然不太明白为什么。说我有以下内容:

@Component
public final class MyComponent {

  private static SomeStaticClass someStaticClass;

  @Autowired
  MyComponent(SomeStaticClass someStaticClass) {
    MyComponent.someStaticClass = someStaticClass;
  }

}

6 个答案:

答案 0 :(得分:8)

为什么这是一个糟糕的设计的几个原因:

  • static可变字段通常是一个糟糕的设计

  • 使测试更加困难 - 一旦设置了这个字段,它将在下一个测试中保持设置,可能会产生隐藏的相互依赖性

  • 如果您想要两个MyComponent个实例,每个实例都有不同的SomeStaticClass,该怎么办?混乱。

  • 您不能通过static字段或setter自动装配注入值,它是明确禁止的。必须有这样的理由。

  • 为什么你甚至需要那个?您在static中有MyComponent种方法吗?为什么呢?

  • 如果上述情况属实,那么在构造函数初始化该字段之前如何阻止调用MyComponent.staticMethod()? Spring的重点是返回完全填充的安全bean

答案 1 :(得分:2)

默认情况下,Spring bean是单例,因此将someStaticClass设为实例字段,并保持代码清洁和可测试。 someStaticClass没有理由是静态的。非最终静态字段是一种气味。

答案 2 :(得分:0)

@Component基本上意味着你的bean默认是Singleton。因此,在其中具有静态依赖性没有多大意义。但它会像你说的那样编译。

答案 3 :(得分:0)

默认情况下,所有Spring bean都是单例,因此在设计类时不需要static

答案 4 :(得分:0)

这是糟糕的设计,因为生命周期不同。即使应用程序上下文关闭,静态变量一旦初始化将继续存在。

另一个不匹配是可能存在多个应用程序上下文。如果SomeStaticClass是注册表怎么办?然后,这将导致混乱,正如托马斯指出的那样。

也有可能在容器初始化之前访问变量。机会大于您的预期:容器中的某个bean在初始化期间可能会调用MyComponent的静态方法,而MyComponent的初始化将在执行之后执行(这是因为bean的依赖关系是在这种情况下隐含,因此IoC容器不知道正确的顺序 - 您将不得不使用@DependsOn注释)

答案 5 :(得分:0)

尽管存在设计缺陷,但如果需要使用上下文初始化静态变量,则应尽快完成。

有几种可能性,其中一些与@Autowired兼容:

  • 让课程实施ApplicationListener或使用ApplicationListener刷新它。
  • 覆盖onRefresh()方法并刷新它。
  • 将bean定义设为第一个,单例按照注册的顺序进行实例化。
  • 在其他一些早期实例化的bean上使用depends-on,MessageSource是一个很好的机会。

很暗,但如果你真的需要它......

其他选项是编写BeanFactoryPostProcessor,手动注入静态字段