是否有可能在Guice范围结束时自动清理资源? [英] Is it possible to automatically clean up resources at the end of scope in Guice?

查看:95
本文介绍了是否有可能在Guice范围结束时自动清理资源?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Let's say I have a Closeable object injected through Guice using request scope:

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

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

Is it possible to hook-up a clean-up method that would automatically call close() on my resource when the scope exists, without resorting to custom scope implementation?

查看自定义在Guice wiki上范围实施指南,它表明范围应该是像这样创建和清理:

Looking at the custom scope implementation guide on the Guice wiki, it shows that scopes should be created and cleaned up like this:

/**
 * 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 中的一些自定义清理代码(尤其是会话和请求范围)。

I am wondering if there is way to hook-up some custom clean-up code in the finally of the built-in scopes (especially session and request scopes).

如果不可能,可能会出现阻碍这种自动清理的问题吗?

If it isn't possible, might there be issues that would discourage this kind of automatic clean-up?

我找到了在servlet容器中实现相同效果的方法通过实施过滤器根据请求创建和清理资源,效果很好,但我很好奇,如果它可能是纯粹的Guice。

I have found ways of achieving the same effect in servlet containers by implementing a Filter to create and clean-up a resource per request, which works great but I am curious if it is possibly with pure Guice.

推荐答案

我自己遇到了类似的问题,最后推出了一个 Disposable 界面,只提供 public void dispose()方法。我发现这对于在某个地方注册监听器并需要在定义的时间取消注册它们的类特别有用。我已经拥有的是我的 AttributeHolderScope ,我博客有关所以我不会在这里重复这一部分。现在唯一缺少的是 AbstractAttributeHolder ,如下所示:

I faced a similar problem myself and finally rolled a Disposable interface which offers nothing but a public void dispose() method. I find this especially valuable for classes that register listeners somewhere and need to unregister them at a defined time. What I already had was my AttributeHolderScope which I blogged about so I won't repeat that part here. The only thing that is missing now is the AbstractAttributeHolder which looks like this:

/**
 * 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 实现来实现,但是可以做到。每次我看这段代码时,我都会问自己,这是不是可以用更简洁的方式完成,但它的工作效果很好(至少对我而言)。

This class itself implements Disposable so you can have nested scopes and when you dispose an outer scope, all nested scopes and, more importantly, all injected instances that implement Disposable get cleaned up. And to precisely answer you question: I don't think that this is possible with the Scope implementations provided by Guice itself, but it can be done. Everytime I look at this code I ask myself if this can't be done in a more concise way, but then it works beautifully (at least for me).

这篇关于是否有可能在Guice范围结束时自动清理资源?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆