2011-01-08 25 views
17

Hãy nói rằng tôi có một đối tượng Closeable tiêm qua Guice sử dụng yêu cầu phạm vi:Có thể tự động xóa tài nguyên ở cuối phạm vi trong Guice không?

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

Có thể treo lên một phương pháp sạch-up mà sẽ tự động gọi close() về tài nguyên của tôi khi phạm vi tồn tại, mà không cần thế nào để triển khai phạm vi tùy chỉnh?

Nhìn vào tùy chỉnh scope implementation guide trên wiki Guice, nó cho thấy rằng phạm vi nên được tạo ra và dọn dẹp như thế này:

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

tôi tự hỏi nếu có cách để treo lên một số tùy chỉnh dọn dẹp mã trong số finally của phạm vi tích hợp (đặc biệt là phạm vi phiên và yêu cầu).

Nếu không thể, có thể có vấn đề khiến bạn không muốn làm sạch tự động?

Tôi đã tìm ra cách để đạt được hiệu quả tương tự trong các thùng chứa servlet bằng cách implementing a Filter để tạo và dọn sạch tài nguyên theo yêu cầu, hoạt động tốt nhưng tôi tò mò nếu nó có thể là với Guice thuần túy.

Trả lời

5

Tôi đã gặp phải sự cố tương tự và cuối cùng đã cuộn giao diện Disposable không cung cấp gì ngoài phương thức public void dispose(). Tôi thấy điều này đặc biệt có giá trị đối với các lớp học đăng ký người nghe ở đâu đó và cần phải hủy đăng ký chúng tại một thời điểm xác định. Những gì tôi đã có là AttributeHolderScope của tôi mà tôi blogged about vì vậy tôi sẽ không lặp lại phần đó ở đây. Điều duy nhất mà là mất tích bây giờ là AbstractAttributeHolder mà trông như thế này:

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

Lớp này tự thực hiện Disposable phạm vi, do đó bạn có thể đã lồng nhau và khi bạn vứt bỏ một phạm vi bên ngoài, tất cả các phạm vi lồng nhau và, quan trọng hơn, tất cả trường hợp được tiêm thực hiện Disposable được dọn dẹp. Và để trả lời chính xác câu hỏi của bạn: Tôi không nghĩ rằng điều này là có thể với việc triển khai Scope được cung cấp bởi chính Guice, nhưng nó có thể được thực hiện. Mỗi khi tôi nhìn vào mã này, tôi tự hỏi bản thân mình nếu điều này không thể được thực hiện một cách ngắn gọn hơn, nhưng sau đó nó hoạt động đẹp (ít nhất là đối với tôi).

+0

Triển khai phạm vi mở rộng, ý tưởng rất hay! Vì vậy, để sử dụng điều này với phạm vi yêu cầu, tôi sẽ tạo 'MyRequestScope' mở rộng lớp phạm vi của bạn từ blog, nối nó vào cùng một vị trí với mặc định' RequestScope' (phần khó), làm 'scope.enter()' với ' AbstractAttributeHolder' và chắc chắn rằng tôi gọi 'dispose()' ở cuối cùng (hoặc trong 'exit()' của 'MyRequestScope')? Nếu bạn có một cách tích hợp tốt, bạn có thể chia sẻ nó (mã và/hoặc kỹ thuật) không? – rodion

+0

Về mã liên quan đến đồng bộ hóa, có vẻ như không cần thiết vì 'AttributeHolder' luôn được truy cập từ' ThreadLocal' do đó một cá thể duy nhất cho mỗi luồng. Tui bỏ lỡ điều gì vậy? – rodion

+0

1) Tôi không sử dụng điều này trong môi trường Servlet, vì vậy tôi không chắc chắn làm thế nào để làm điều này đúng cách. – Waldheinz

Các vấn đề liên quan