我目前正在开发一个大型的非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 那会很棒,但我现在无法证明这样的大型重构是合理的。
但是如何让SomeInstance
Spring管理并仍保持getInstance()
方法以实现向后兼容?
我想到了这样的事情:
public static SomeInstance getInstance() {
return ApplicationContext.getBean("someInstanceBean");
}
但是,可能无法从静态上下文调用getBean()
方法...
关于如何处理这个的任何想法?
答案 0 :(得分:3)
在您的应用程序上下文XML文件中,您需要做的就是编写如下条目:
<bean id="thing" name="thing" class="com.example.ThingSingleton"
factory-method="getInstance">
</bean>
没有理由更改现有的API。您现有的API强制声明或指定为单例的实际上是单例。这很好,值得保留。 Spring是一种方便的方法,可以使用类的Plain Old Java API将POJO连接在一起,而不是构造函数,工厂方法等的替代方法。
完成后,您可以对自己说“我的代码都不应该调用com.example.ThingSingleton.getInstance()
,所以我应该将其标记为@Deprecated
,这是我使用之前的遗留物弹簧”。但这是非常错误的。在任何真正意义上,该方法都不是已弃用:您明确告诉Spring使用它,这不是一个错误。该方法仍然是获得Singleton实例的唯一批准方式。 恰好发生,没有代码你写入它。 不推荐使用并不意味着“我的代码中未使用”。这意味着“不应该使用,因为将来很可能被删除”。您不会删除getInstance()
方法,是吗?
答案 1 :(得分:0)
您可以创建一个单例来保存上下文。像这样的东西可能对你有用。 由于ApplicationContextAware接口,ApplicationContext将在启动期间自动设置。
有可能上下文将为null,您可能希望减轻它,但是如果Spring正确初始化则不应该是一个问题。
@Component
public class TestClass implements ApplicationContextAware {
private static ApplicationContext context = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static Object getBean(String beanName){
return context.getBean(beanName);
}
}