我目前正在开发一个大型的非 Spring 代码库。 我想将 Spring Context 引入代码库,但我想逐步进行。
我想要解决的首要挑战之一是“Springify”一个在代码中大量使用的大型单例对象。
单例在代码中的使用如下:
SomeInstance instance = SomeInstance.getInstance();
instance.doSomething()
单例对象包含一个字段和方法,如下所示:
class SomeInstance {
private static SomeInstance instance;
public static SomeInstance getInstance(){
if(instance == null){
instance = new SomeInstance();
}
return instance;
}
好的,这可行,但我想让 SomeInstance
类成为 Spring bean。
没问题:
@Component
class SomeInstance {
...
}
但是我仍然想保留 getInstance()
静态方法,并使其返回单例实例,以便向后兼容,而不必重构所有内容。
如果我想摆脱代码中各处的 getInstance()
方法,这意味着一次巨大的重构:
- 创建使用
SomeInstance
Spring beans 的所有对象 - 使用 @Autowired 连接到单例
那太好了,但我现在无法证明这样的大规模重构是合理的。
但是如何使 SomeInstance
由 Spring 管理,同时仍然保留 getInstance()
方法以实现向后兼容性?
我想到了这样的事情:
public static SomeInstance getInstance() {
return ApplicationContext.getBean("someInstanceBean");
}
但是,getBean()
方法可能无法从静态上下文中调用...
关于如何处理这个问题有什么想法吗?
最佳答案
在应用程序上下文 XML 文件中,您所需要做的就是编写如下所示的条目:
<bean id="thing" name="thing" class="com.example.ThingSingleton"
factory-method="getInstance">
</bean>
没有理由更改您现有的 API。您现有的 API 强制要求声明或指定为单例的内容实际上是单例。这很好,值得保留。 Spring 旨在成为一种使用普通旧式 Java API 类将 POJO 连接在一起的便捷方式,而不是构造函数、工厂方法等的替代品。
完成此操作后,您可能会对自己说“我的代码都不应该调用 com.example.ThingSingleton.getInstance()
,因此我应该将其标记为 @Deprecated
,这是我使用 Spring 之前的时代的遗迹”。但这是完全错误的。该方法在任何真正意义上都没有被弃用:您明确地告诉 Spring 使用它,这不是一个错误。该方法仍然是唯一获得认可的获取 Singleton 实例的方法。 恰好您编写的代码没有调用它。 已弃用并不意味着“在我的代码中未使用”。它的意思是“不应使用,因为将来可能会被删除”。您不会删除该 getInstance()
方法,对吗?
关于spring - 如何从单例模式迁移到Spring?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25847350/