【问题标题】:Is it possible to automatically clean up resources at the end of scope in Guice?是否可以在 Guice 范围结束时自动清理资源?
【发布时间】:2011-01-08 15:32:10
【问题描述】:

假设我有一个使用请求范围通过 Guice 注入的 Closeable 对象:

@Provides @RequestScoped
public MyCloseableResource providesMyCloseableResource(){
  return new MyCloseableResourceImpl();
}

是否可以连接一个清理方法,当范围存在时自动调用我的资源上的close(),而不求助于自定义范围实现?

查看 Guice wiki 上的自定义 scope implementation guide,它表明应该像这样创建和清理范围:

/**
 * Runs {@code runnable} in batch scope.
 */
public void scopeRunnable(Runnable runnable) {
  scope.enter();
  try {
    // explicitly seed some seed objects...
    scope.seed(Key.get(SomeObject.class), someObject);
    // create and access scoped objects
    runnable.run();
  } finally {
    scope.exit();
  }
}

我想知道是否有办法在内置范围(尤其是会话和请求范围)的 finally 中连接一些自定义清理代码。

如果不可能,是否存在阻碍这种自动清理的问题?

我已经通过implementing a Filter 找到了在 servlet 容器中实现相同效果的方法,可以根据请求创建和清理资源,效果很好,但我很好奇它是否可能是纯 Guice。

【问题讨论】:

    标签: java guice


    【解决方案1】:

    我自己也遇到过类似的问题,最后推出了一个Disposable 接口,它只提供public void dispose() 方法。我发现这对于在某处注册侦听器并需要在定义的时间取消注册它们的类特别有价值。我已经拥有的是我的AttributeHolderScope,我是blogged about,所以我不会在这里重复这部分。现在唯一缺少的是AbstractAttributeHolder,它看起来像这样:

    /**
     * An anstract base class for implementing the {@link AttributeHolder}
     * interface which has an implementation of the attribute related methods.
     *
     * @author Matthias Treydte <waldheinz at gmail.com>
     */
    public abstract class AbstractAttributeHolder
            implements AttributeHolder, Disposable {
    
        private final Object lock = new Object();
        private transient Map<Object, Object> attributes;
    
        public AbstractAttributeHolder() {
            this.attributes = new HashMap<Object, Object>();
        }
    
        public void replaceAttributes(Map<Object, Object> newAttr) {
            synchronized (getAttributeLock()){
                this.attributes = newAttr;
            }
        }
    
        @Override
        public Object getAttributeLock() {
            return this.lock;
        }
    
        @Override
        public final void putAttribute(Object key, Object value) {
            synchronized (getAttributeLock()) {
                attributes.put(key, value);
            }
        }
    
        @Override
        public final boolean hasAttribute(Object key) {
            synchronized (getAttributeLock()) {
                return attributes.containsKey(key);
            }
        }
    
        @Override
        public final Object getAttribute(Object key) {
            synchronized (getAttributeLock()) {
                return attributes.get(key);
            }
        }
    
        @Override
        public final Set<Object> getAttributes() {
            synchronized (getAttributeLock()) {
                return Collections.unmodifiableSet(
                        new HashSet<Object>(this.attributes.values()));
            }
        }
    
        @Override
        public void dispose() {
            synchronized (this.getAttributeLock()) {
                for (Object o : this.attributes.values()) {
                    if (o instanceof Disposable) {
                        final Disposable d = (Disposable) o;
                        d.dispose();
                    }
                }
    
                this.attributes.clear();
            }
        }
    }
    

    这个类本身实现了Disposable,所以你可以有嵌套的作用域,当你处理一个外部作用域时,所有的嵌套作用域,更重要的是,所有实现Disposable的注入实例都会被清理干净。为了准确回答您的问题:我认为 Guice 本身提供的 Scope 实现不可能做到这一点,但可以做到。每次我看这段代码时,我都会问自己是否不能以更简洁的方式完成,但它工作得很好(至少对我来说)。

    【讨论】:

    • 一个可扩展的范围实现,非常好的主意!因此,要将其与请求范围一起使用,我将创建 MyRequestScope 从博客扩展您的范围类,将其连接到与默认 RequestScope 相同的位置(棘手的部分),使用 AbstractAttributeHolder 执行 scope.enter() 并制作确定我最后打电话给dispose()(或MyRequestScopeexit())?如果你有一个很好的集成方式,你可以分享它(代码和/或技术)吗?
    • 关于同步相关的代码,似乎没有必要,因为AttributeHolder 总是从ThreadLocal 访问,因此每个线程只有一个实例。我错过了什么吗?
    • 1) 我不在 Servlet 环境中使用它,所以我不确定如何正确执行此操作。
    • 2) 这取决于您如何使用代码,我需要同步,因为对我而言,在任何给定时间,Scope 中可能有多个线程,因此我认为需要同步。
    • 1) 谢谢!对范围中缺乏自动清理感到羞耻。本来是有用的。无论如何,您的方法似乎总体上效果很好!如果有人感兴趣,可以使用 servlet 过滤器来完成集成,就像这里描述的那样:blog.yanivkessler.com/2010/06/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-02-24
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 2010-11-06
    • 2022-11-15
    • 1970-01-01
    相关资源
    最近更新 更多