2010-10-21 25 views
12

Có điều tôi không hiểu về guice: Theo những gì tôi đã đọc cho đến nay, tôi chỉ nên sử dụng Injector trong lớp bootstrapping của mình (trong một ứng dụng độc lập, nó thường nằm trong main() phương pháp), như trong ví dụ bên dưới (lấy từ tài liệu guice):Làm thế nào để tránh có injector.createInstance() trên khắp nơi khi sử dụng guice?

public static void main(String[] args) { 
    /* 
    * Guice.createInjector() takes your Modules, and returns a new Injector 
    * instance. Most applications will call this method exactly once, in their 
    * main() method. 
    */ 
    Injector injector = Guice.createInjector(new BillingModule()); 

    /* 
    * Now that we've got the injector, we can build objects. 
    */ 
    RealBillingService billingService = injector.getInstance(RealBillingService.class); 
    ... 
    } 

Nhưng nếu không phải tất cả các đối tượng tôi cần có thể được tạo trong khi khởi động thì sao? Có lẽ tôi muốn trả lời một số tương tác của người dùng khi ứng dụng đang chạy? Tôi không phải giữ cho vòi phun của tôi xung quanh một nơi nào đó (ví dụ như một biến tĩnh) và sau đó gọi injector.getInstance (SomeInterface.class) khi tôi cần phải tạo một đối tượng mới?

Tất nhiên, việc chuyển các cuộc gọi đến Injector.getInstance() trên toàn bộ địa điểm có vẻ không đáng mong muốn.

Tôi đang gặp vấn đề gì ở đây?

Trả lời

12

Có, về cơ bản, bạn chỉ nên sử dụng Bộ phun để tạo ra thể hiện cho đối tượng gốc. Phần còn lại của ứng dụng không được chạm vào Vùng chứa-Guice. Như bạn đã nhận thấy, bạn vẫn cần phải tạo một số đối tượng khi được yêu cầu. Có nhiều cách tiếp cận khác nhau để thực hiện điều đó, mỗi phương pháp phù hợp với các nhu cầu khác nhau.

Tiêm nhà cung cấp Provider là giao diện từ Guice. Nó cho phép bạn yêu cầu một thể hiện mới của một đối tượng. Đối tượng đó sẽ được tạo ra bằng cách sử dụng Guice. Ví dụ.

class MyService{ 
    private Provider<Transaction> transactionProvider; 
    public MainGui(Provider<Transaction> transactionProvider){ 
     this.transactionProvider = transactionProvider; 
    } 

    public void actionStarted(){ 
     Transaction transaction = transactionProvider.get(); 
    } 

Xây dựng một Nhà máy Thông thường bạn cần một số loại nhà máy. Nhà máy này sử dụng một số dịch vụ được tiêm và một số tham số và tạo một đối tượng mới cho bạn. Sau đó, bạn sử dụng nhà máy này cho các phiên bản mới. Sau đó, bạn tiêm nhà máy đó và sử dụng nó. Ngoài ra, còn giúp đỡ điều này với AssistedInject -extension

Tôi nghĩ rằng với hai khả năng này bạn hiếm khi cần sử dụng chính Guice-Injector. Tuy nhiên đôi khi vẫn thích hợp để sử dụng chính vòi phun. Sau đó, bạn có thể tiêm Injector vào một thành phần.

3

Để mở rộng câu trả lời của Gamlor được đăng, bạn cũng cần phải phân biệt giữa các loại đối tượng bạn đang sử dụng.

Đối với dịch vụ, việc tiêm là giải pháp đúng, tuy nhiên, đừng cố gắng luôn làm cho các đối tượng dữ liệu (thường là các lá trong đồ thị đối tượng) có thể tiêm được. Có thể có những tình huống mà đó là giải pháp đúng, nhưng việc tiêm một Provider<List> có lẽ không phải là một ý tưởng tốt. Một đồng nghiệp của tôi đã kết thúc làm điều đó, nó làm cho cơ sở mã rất khó hiểu sau một thời gian. Chúng tôi vừa hoàn thành việc dọn dẹp tất cả và mô-đun Guice giờ đây cụ thể hơn nhiều.

+0

Có, tôi hoàn toàn đồng ý với điều đó. – Gamlor

0

Trong trừu tượng, tôi nghĩ ý tưởng chung là nếu đáp ứng với sự kiện người dùng là một phần của khả năng của ứng dụng của bạn, sau đó, cũng ...

BillingService billingService = injector.getInstance(BillingService.class); 
billingService.respondToUserEvent(event); 

Tôi đoán rằng có thể là một chút trừu tượng , nhưng ý tưởng cơ bản là bạn nhận được từ Guice lớp ứng dụng cấp cao nhất của bạn. Đánh giá từ câu hỏi của bạn, tôi đoán rằng có lẽ BillingService không phải là lớp học cấp cao nhất của bạn?

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