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

问题描述 投票:3回答:6

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

@Component
public final class MyComponent {

  private static SomeStaticClass someStaticClass;

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

}
java spring static dependency-injection
6个回答
8
投票

设计糟糕的原因很少:

  • static可变字段一般都是糟糕的设计
  • 使测试更难 - 一旦设置了这个字段,它将在下一个测试中保持设置,可能会产生隐藏的相互依赖性
  • 如果你想有两个MyComponent实例,每个都有不同的SomeStaticClass怎么办?混沌。
  • 你不能通过static字段或setter autowiring注入值,它是明确禁止的。必须有这样的理由。
  • 为什么你甚至需要那个?你在staticMyComponent方法吗?为什么?
  • 如果上述情况属实,那么在构造函数初始化该字段之前如何阻止调用MyComponent.staticMethod()? Spring的重点是返回完全填充的安全bean

2
投票

Spring bean默认是单例,所以让someStaticClass成为一个实例字段,并保持代码清洁和可测试。 someStaticClass没有理由保持静止。非最终静态字段是一种气味。


0
投票

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


0
投票

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


0
投票

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

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

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


0
投票

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

有几种可能性,一些与@Autowired兼容的是:

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.