2011-01-08 33 views
17

Talep kapsamını kullanarak Guice ile enjekte edilen bir Closeable nesnesinin olduğunu düşünelim:Guice'de kapsamın sonunda kaynakların otomatik olarak temizlenmesi mümkün mü?

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

Kapsam mevcut olduğunda, kaynak mevcut olduğunda close()'u otomatik olarak arayacak bir temizleme yönteminin kullanılması mümkün mü? özel kapsam uygulaması?

Guice wiki üzerindeki scope implementation guide modeline baktığımızda, bu kapsamın şu şekilde oluşturulup temizlendiğini gösteriyor:

/** 
* 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(); 
    } 
} 

Bazı özel temizlemeleri yapmanın bir yolu olup olmadığını merak ediyorum. Yerleşik kapsamların finally'ındaki kodu (özellikle oturum ve istek kapsamları).

Mümkün değilse, bu tür otomatik temizlemeyi engelleyen sorunlar olabilir mi?

implementing a Filter ile aynı etkiyi elde etmenin yollarını, istek başına bir kaynak oluşturmak ve temizlemek için yollar buldum, bu harika çalışıyor ancak saf Guice ile muhtemelen merak ediyorum.

cevap

5

Kendime benzer bir sorunla karşılaştım ve en sonunda public void dispose() yönteminden başka bir şey sunmayan bir Disposable arabirimi yuvarlandı. Bunu özellikle dinleyicileri bir yere kaydeden ve tanımlanmış bir zamanda onları silmeye ihtiyaç duyan sınıflar için değerli buluyorum. Zaten sahip olduğum blogged aboutAttributeHolderScope benim bu yüzden burada bu bölüm tekrar etmeyeceğim. Şimdi eksik olan tek şey bu gibi görünüyor AbstractAttributeHolder geçerli:

/** 
* 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(); 
     } 
    } 
} 

Bu sınıf kendisi Disposable böylece iç içe geçmiş olabilir kapsamları uygulayan ve bir dış kapsamını çöpe atarken tüm iç içe kapsamları ve daha da önemlisi, bütün Disposable uygulanmış enjekte örnekleri temizlenir. Ve kesin olarak size soruya cevap vermek için: Bunun, Guice tarafından sağlanan Scope uygulamalarıyla mümkün olduğunu düşünmüyorum, ancak bu yapılabilir. Bu koda baktığım her seferinde kendime, daha özlü bir şekilde yapılamazsa kendime soruyorum, ama sonra güzelce çalışıyor (en azından benim için).

+0

Genişletilebilir bir kapsam uygulaması, çok iyi bir fikir! Bu nedenle, istek kapsamı ile kullanabilmek için, 'MyRequestScope'unu kapsam sınıfınızı blog'undan genişletecek, varsayılan 'RequestScope'la aynı yere bağlayacağım (zor kısmı),' scope.enter()' ile AbstractAttributeHolder' ve 'dispose() 'olarak adlandırdığımdan son olarak (veya' MyRequestScope'un 'exit()') emin olun? Eğer bunu entegre etmenin güzel bir yolu varsa, bunu paylaşır mısınız (kod ve/veya teknikler) lütfen? – rodion

+0

Senkronizasyonla ilgili kodla ilgili olarak, "AttributeHolder" öğesine her zaman ThreadLocal'den erişildiği için gereksizdir çünkü her iş parçacığı için benzersiz bir örnek. Bir şey mi eksik? – rodion

+0

1) Bunu bir Servlet ortamında kullanmıyorum, dolayısıyla bunu nasıl düzgün yapacağımı bilmiyorum. – Waldheinz

İlgili konular