问题描述
考虑一下我有一个Spring Service
bean的情况,它依赖于其他可能暴露AutoCloseable
接口的bean。我通常会问这个问题,稍后再解释我的具体需求。
public class ServiceBean {
@Autowired private ResourceBean resource; //Resource is Closeable
}
根据配置,在某些配置下,Resource
是全局单例,在其他情况下,它是原型。由于我正在编写库,因此要求我提供一定程度的灵活性。
如果resource
是单例,则在关闭ApplicationContext之前,永远不要close()
。否则,如果resource
是为我的ServiceBean
实例创建的原型(是原型,我从设计上就知道这一点),则它必须在close()
的生命周期结束时被丢弃(ServiceBean
d。
步骤1:关闭ServiceBean
这不是一件坏事。编程方面的最佳实践表明,当您的班级依赖可支配资源时,应将其声明为可支配资源,并包含在try-with-resources块中
public class ServiceBean implements AutoCloseable {
@Autowired private ResourceBean resource; //Resource is Closeable
public void close() throws Exception {
resource.close(); //what the!!!
}
}
此设置的问题在于,如果资源是原型,则它将在第一时间关闭。
Spring提供了以String作为参数的方法isPrototype
和isSingleton
,因此我推断出它们是用于bean名称的,在这种情况下我不希望知道
问题:在原型bean中配置原型资源的正确方法应该是什么?当ApplicationContext关闭时,Spring AFAIK仅处理单例
我的具体情况
我有一个ThreadPoolTaskExecutor
要注入。它可能是单例对象或原型对象,shutdown
对于清除未完成线程中的池很有用
解决方法
我想到了一个主意(一个疯狂的主意,尚未验证)。
注入的资源bean可以利用BeanFactory<>
类。
-
通过工厂声明
Resource
公共类ResourceBeanFactoryBean扩展了AbstractFactoryBean
-
参数化单调性
AbstractFactoryBean公开isSingleton
-
在单例状态下将返回的bean包装为不可关闭的
受保护的ResourceBean createInstance(){
return isSingleton() ? myBean : wrapNonCloseable(myBean);
}
其中myBean
是您通常会创建的实例,而wrapNonCloseable
是一种实用程序方法,它扩展了close
方法无所事事
protected MyResourceBean wrapNonCloseable(MyResourceBean bean) {
return new MyResourceBean()
{
//Delegate all methods to the original bean
public void close(){}
}
}