是否可以在Guice的范围结束时自动清理资源?

rod*_*ion 17 java guice

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

@Provides @RequestScoped
public MyCloseableResource providesMyCloseableResource(){
  return new MyCloseableResourceImpl();
}
Run Code Online (Sandbox Code Playgroud)

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

查看Guice wiki上的自定义范围实现指南,它显示应该创建和清理范围,如下所示:

/**
 * 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();
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

我已经找到了在servlet容器中实现相同效果的方法,通过实现Filter来为每个请求创建和清理资源,这很有效,但我很好奇它是否可能与纯Guice一起使用.

Wal*_*inz 5

我自己也遇到了类似的问题,最后推出了一个Disposable只提供public void dispose()方法的界面.我发现这对于在某个地方注册监听器并且需要在定义的时间取消注册它们的类特别有价值.我已经有是我的AttributeHolderScope,我的博客上讲述,所以我不会在这里重复的部分.现在唯一缺少的是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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这个类本身实现,Disposable因此你可以拥有嵌套的作用域,当你处理一个外部作用域时,所有嵌套的作用域,更重要的是,所有注入实例的实例都Disposable被清理掉了.并准确地回答你的问题:我不认为这可以Scope通过Guice本身提供的实现来实现,但它可以做到.每次我看这段代码时,我都会问自己,这是不是可以用更简洁的方式完成,但是它的工作效果很好(至少对我而言).