正确不处置单例Spring bean

问题描述

考虑一下我有一个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作为参数的方法isPrototypeisSingleton,因此我推断出它们是用于bean名称的,在这种情况下我不希望知道

问题:在原型bean中配置原型资源的正确方法应该是什么?当ApplicationContext关闭时,Spring AFAIK仅处理单例

我的具体情况

我有一个ThreadPoolTaskExecutor要注入。它可能是单例对象或原型对象,shutdown对于清除未完成线程中的池很有用

解决方法

我想到了一个主意(一个疯狂的主意,尚未验证)。

注入的资源bean可以利用BeanFactory<>类。

  1. 通过工厂声明Resource

    公共类ResourceBeanFactoryBean扩展了AbstractFactoryBean

  2. 参数化单调性

AbstractFactoryBean公开isSingleton

  1. 在单例状态下将返回的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(){}
    }
}