3

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

@Component
public final class MyComponent {

  private static SomeStaticClass someStaticClass;

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

}
4

6 回答 6

8

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

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

  • 使测试更难 - 一旦设置了这个字段,它将在下一个测试中保持设置,可能会创建隐藏的相互依赖关系

  • 如果你想有两个实例MyComponent,每个实例都有不同的SomeStaticClass?混乱。

  • 您不能通过static字段或设置器自动装配注入值,这是明确禁止的。这一定是有原因的。

  • 你为什么需要那个?你有static方法MyComponent吗?为什么?

  • 如果上述情况属实,您如何防止MyComponent.staticMethod()在构造函数初始化该字段之前调用?Spring 的全部意义在于返回完全填充、安全的 bean

于 2012-12-18T19:40:37.580 回答
2

Spring bean 默认是单例的,所以创建someStaticClass一个实例字段,并保持你的代码干净和可测试。没有理由someStaticClass保持静止。非最终静态字段是一种气味。

于 2012-12-18T19:38:36.500 回答
0

Despite of the design flaws, if you need to initialize a static variable with context it should be done as soon as possible.

There are several possibilities, some that are compatible with @Autowired are:

  • Let class to implement ApplicationListener or use an ApplicationListener to refresh it.
  • Override onRefresh() method and refresh it.
  • Make the bean definition the first one, singleton are instantiated in the same order that registered.
  • Use depends-on on on some other early instatiated bean, a MessageSource is a good chance.

Is quite dark, but if you really need it...

Other option is write a BeanFactoryPostProcessor an inject the static field by hand

于 2012-12-18T22:09:54.373 回答
0

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

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

也有可能在容器初始化之前访问该变量。机会比你想象的要大:容器中的某些 bean 可能会在其初始化期间调用静态MyComponent方法MyComponent不知道正确的顺序 - 你必须使用@DependsOn注释)

于 2012-12-18T19:56:42.797 回答
0

@Component基本上意味着你的bean默认是单例的。因此,在其中具有静态依赖关系没有多大意义。但它会按照你说的编译。

于 2012-12-18T19:38:35.073 回答
0

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

于 2012-12-18T19:38:54.700 回答