2009-05-23 51 views
13

Tôi tiếp tục muốn thử điều này trên quy mô lớn hơn với hệ thống + ứng dụng + xây dựng của chúng tôi, nhưng ưu tiên cao hơn tiếp tục đẩy nó vào ổ ghi sau. Nó có vẻ giống như một cách tốt đẹp để tải các mô-đun Guice và tránh khiếu nại phổ biến về "cấu hình mã hóa cứng". Các thuộc tính cấu hình riêng hiếm khi thay đổi, nhưng hầu như bạn sẽ luôn có một bộ hồ sơ, thường là cho các môi trường khác nhau (Debug, Production, ...).Có ai đã sử dụng ServiceLoader cùng với Guice không?

ServiceLoader cho phép bạn kéo danh sách tất cả các triển khai được định nghĩa là dịch vụ cho một loại nhất định. Đưa này cùng với Guice, bạn kết thúc với:

import java.util.ServiceLoader; 

import com.google.inject.AbstractModule; 
import com.google.inject.Module; 

public class ModuleLoader<M extends Module> extends AbstractModule { 

    private final Class<M> type; 

    public ModuleLoader(Class<M> type) { 
     this.type = type; 
    } 

    public static <M extends Module> ModuleLoader<M> of(Class<M> type) { 
     return new ModuleLoader<M>(type); 
    } 

    @Override 
    protected void configure() { 
     ServiceLoader<M> modules = ServiceLoader.load(type); 
     for (Module module : modules) { 
      install(module); 
     } 
    } 
} 

dụ sử dụng (như một bộ nạp servlet động trong một dự án Guice-servlet):

import com.google.inject.servlet.ServletModule; 

public class ServletLoader extends GuiceServletContextListener { 
    @Override 
    protected final Injector getInjector() { 
     return Guice.createInjector(ModuleLoader.of(ServletModule.class); 
    } 
} 

Các dịch vụ (đóng gói như module) sẽ là đóng gói trong các tập tin jar riêng biệt. Trong mỗi bạn sẽ định nghĩa lớp (es) trong meta-data:

Within servlets.jar: META-INF/services/com.google.inject.Module 

com.example.webapps.MyServletModuleA 
com.example.webapps.MyServletModuleB 

Kể từ khi chúng tôi sử dụng Maven, chúng tôi nghĩ rằng đây sẽ là lý tưởng như chúng ta có thể kéo trong việc triển khai khác nhau khi chạy qua phụ thuộc hồ sơ. Có ai đang sử dụng Guice như thế này không?

Nếu không, vui lòng sử dụng ví dụ này và xem nó hoạt động như thế nào cho bạn. (ServiceLoader chỉ được hỗ trợ trong JDK6 +)

+0

Bạn có thể trợ giúp không? Tôi đang cố gắng để làm một cái gì đó tương tự nhưng có một vấn đề noobie với ServiceLoader? http://stackoverflow.com/questions/28983997/java-cant-get-a-working-serviceloader – tommed

Trả lời

3

Chúng tôi đang thực hiện gần như chính xác công việc này. Chúng tôi hiện đang bị kẹt trong java 5 do một số hạn chế nội bộ, do đó chúng tôi thực hiện một chút khác biệt bằng cách sử dụng Nhà cung cấp dịch vụ (do không có quyền truy cập ServiceLocator cho đến java 6 như bạn đã đề cập), nhưng về cơ bản nó hoạt động giống nhau.

Tôi nhớ đọc ở đâu đó rằng đây là một trong những cách ưa thích mà các nhà phát triển Guice đề xuất, mặc dù họ muốn mở tính linh hoạt này.

1

Tôi đã xem xét cách này nhưng tôi đã không sử dụng nó vì tôi sợ, rằng tôi phải giữ mô-đun của tôi cực kỳ nhỏ, bởi vì nó không thể ràng buộc cùng một giao diện hai lần. Vấn đề của tôi là, nếu tôi muốn sử dụng một giao diện/lớp/enum/bất cứ thứ gì từ một cái bình khác và cái bình đó đã định nghĩa một tập tin/dịch vụ tôi bị hỏng, vì tôi không thể sử dụng nội dung của bình mà không tải nó như một mô-đun.

Tôi hy vọng mối quan tâm của tôi rõ ràng.

0

"vì không thể liên kết cùng một giao diện hai lần".

Điều này thực sự sai! Với Multibinder của Guice, có một cách để làm việc với các triển khai khác nhau của cùng một giao diện, có thể bị ràng buộc trong các mô-đun khác nhau.

Tôi đến một giải pháp hơi khác với tải thực tế hơn Mark Renouf (ModuleLoader của anh ấy trông thực sự tốt hơn), nhưng bài đăng trên blog của tôi có thể hiển thị thêm một chút về môi trường nơi áp dụng phương pháp này (Plugins) và tiện ích mở rộng các điểm trông giống như:

Guice 2.0 Multibinder + Java ServiceLoader = Plugin mechanism

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