我知道这个编译,但我的问题是,这是一个好主意吗?我很好奇为什么它可能不是一个好主意。更好的是,如果SomeStaticClass
是@Component
,还有其他方法,但它也必须是MyComponent
的静态成员。我的理解是它的设计很糟糕,让Spring自动装配静态成员。根据我所读到的,我仍然不太明白为什么。说我有以下内容:
@Component
public final class MyComponent {
private static SomeStaticClass someStaticClass;
@Autowired
MyComponent(SomeStaticClass someStaticClass) {
MyComponent.someStaticClass = someStaticClass;
}
}
答案 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()
方法并刷新它。depends-on
,MessageSource是一个很好的机会。很暗,但如果你真的需要它......
其他选项是编写BeanFactoryPostProcessor,手动注入静态字段