Подтвердить что ты не робот

Можно ли автоматически очищать ресурсы в конце области действия в Guice?

Скажем, у меня есть объект Closeable, введенный через Guice с использованием области запроса:

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

Можно ли подключить метод очистки, который автоматически вызовет close() на моем ресурсе, когда область существует, не прибегая к реализации пользовательской области видимости?

Глядя на руководство по реализации области в вики Guice, он показывает, что области должны быть созданы и очищены следующим образом:

/**
 * 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 встроенных областей (особенно области сеанса и запроса).

Если это невозможно, могут возникнуть проблемы, которые препятствовали бы такой автоматической очистке?

Я нашел способы достижения такого же эффекта в контейнерах сервлетов с помощью реализации фильтра для создания и очистки ресурса за запрос, который отлично работает, но я Любопытно, если это возможно с чистым Guice.

4b9b3361

Ответ 1

Я сам столкнулся с подобной проблемой и, наконец, развернул интерфейс 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();
        }
    }
}

Этот класс сам реализует Disposable, так что вы можете иметь вложенные области, и когда вы располагаете внешнюю область, все вложенные области и, что более важно, все внедренные экземпляры, которые реализуют Disposable, очищаются. И чтобы точно ответить на ваш вопрос: я не думаю, что это возможно с реализациями Scope, предоставленными самим Guice, но это можно сделать. Каждый раз, когда я смотрю на этот код, я спрашиваю себя, нельзя ли сделать это более кратким способом, но тогда он работает прекрасно (по крайней мере, для меня).