我知道这个编译,但我的问题是,这是一个好主意吗?我很好奇为什么它可能不是一个好主意。更好的是,如果SomeStaticClass
是@Component
,还有其他选择,但它也必须是MyComponent
的静态成员。我的理解是它的设计很糟糕,让Spring自动装配静态成员。根据我所读到的,我仍然不太明白为什么。说我有以下内容:
@Component
public final class MyComponent {
private static SomeStaticClass someStaticClass;
@Autowired
MyComponent(SomeStaticClass someStaticClass) {
MyComponent.someStaticClass = someStaticClass;
}
}
设计糟糕的原因很少:
static
可变字段一般都是糟糕的设计MyComponent
实例,每个都有不同的SomeStaticClass
怎么办?混沌。static
字段或setter autowiring注入值,它是明确禁止的。必须有这样的理由。static
有MyComponent
方法吗?为什么?MyComponent.staticMethod()
? Spring的重点是返回完全填充的安全beanSpring bean默认是单例,所以让someStaticClass
成为一个实例字段,并保持代码清洁和可测试。 someStaticClass
没有理由保持静止。非最终静态字段是一种气味。
@Component
基本上意味着你的bean默认是Singleton。因此,在其中具有静态依赖性没有多大意义。但它会像你说的那样编译。
默认情况下,所有Spring bean都是单例,因此在设计类时不需要static
。
这是糟糕的设计,因为生命周期不同。即使应用程序上下文关闭,静态变量一旦初始化将继续存在。
另一个不匹配的是,可能存在多个应用程序上下文。如果SomeStaticClass
是注册表怎么办?然后,这将导致混乱,正如托马斯所指出的那样。
此外,有可能在容器初始化之前访问变量。机会大于你的期望:容器中的某个bean在初始化期间可能会调用MyComponent
的静态方法,而MyComponent
的初始化将在之后执行(这是因为在这种情况下bean依赖性是隐含的,因此IoC容器不知道正确的顺序 - 你将不得不使用@DependsOn
注释)
尽管存在设计缺陷,但如果需要使用上下文初始化静态变量,则应尽快完成。
有几种可能性,一些与@Autowired
兼容的是:
ApplicationListener
或使用ApplicationListener
来刷新它。onRefresh()
方法并刷新它。depends-on
,MessageSource是一个很好的机会。很黑,但如果你真的需要它......
其他选项是编写BeanFactoryPostProcessor,手动注入静态字段