2011-11-08 14 views
8

Tôi đang gặp một số khó khăn khi hiểu được cách thức hoạt động đơn âm của Guice. Tôi đã đọc tài liệu sẵn có (ở đây - http://code.google.com/p/google-guice/wiki/Scopes), nhưng tôi vẫn không thể tìm ra một số thứ:Guice eager/lazy singleton instantiations

1) Tôi đã tích hợp Guice với Tomcat và tôi đã thiết lập một số ràng buộc trong ServletModule:

bind(MyServlet.class).asEagerSingleton(); 
serve("myUrl").with(MyServlet.class); 
serve("myOtherUrl").with(MyOtherServlet.class); 

(nơi lớp MyOtherServlet có một chú thích @Singleton trên nó) My Mục đích ở đây là để có hai servlets, nơi người ta đang háo hức khởi tạo, trong khi người kia thì không. Tuy nhiên có vẻ như dòng "serve ... with ..." tự động khởi tạo các đối tượng servlet, mặc dù lớp đó không bị ràng buộc như một singleton mong muốn. Các liên kết tôi đính kèm ở trên đề cập đến sự khác biệt giữa Guice chạy dưới Stage.Development và Stage.Production - tuy nhiên điều này vẫn xảy ra ngay cả khi tôi sử dụng rõ ràng Stage.Development (đó là mặc định một anyway). Có cách nào để tránh điều này không?

2) (tiếp tục 1) Cố gắng đảm bảo rằng MyServlet được khởi tạo ngay trước khi tất cả servlet khởi tạo háo hức ngay bây giờ, tôi đã sửa đổi thứ tự của mô-đun (và câu lệnh ràng buộc) khi tạo Injector, để ràng buộc cho MyServlet xuất hiện đầu tiên. Tuy nhiên, tôi thấy rằng nó vẫn được instantiated muộn hơn một số ràng buộc khác (các lớp phi servlet), trong đó đã có dạng:

bind(MyInterface.class).to(MyClass.class).asEagerSingleton() 

mặc dù những cam kết ràng buộc khác xuất hiện sau này trong các module/bindings trật tự. Tôi đã xem xét nó, và thấy rằng Guice đơn giản là tạo ra các trình đơn mong muốn bị ràng buộc bởi dạng "bind ... to ... asEagerSingleton()" trước khi nó thực hiện "bind" asEagerSingleton() " và vì vậy tôi đã giải quyết nó bằng cách sửa đổi dòng: bind (MyServlet.class) .asEagerSingleton(); vào: liên kết (MyServletDummyInterface.class) .to (MyServlet.class) .asEagerSingleton()

và thực tế đã hoạt động. Tuy nhiên, tôi muốn tránh có một giao diện giả chỉ để giải quyết điều này, vì vậy tôi đã tự hỏi nếu có ai có một giải pháp tốt hơn cho điều này ..?

3) Tôi có hai mô-đun Guice - một ServletModule và một AbstractModule. Các configureServlets ServletModule() đã sau ràng buộc trong đó:

serve("aUrl").with(SomeServlet.class); 

cấu hình của AbstractModule() có các ràng buộc sau:

bind(SomeImpl.class).asEagerSingleton(); 
bind(SomeInterface.class).to(SomeImpl.class).in(Singleton.class); 

Bên cạnh đó, Lớp SomeServlet có một lĩnh vực tiêm loại SomeInterface, và có chú thích @Singleton ở đầu lớp.

Bây giờ, người ta có thể mong đợi rằng khi tạo một bộ phun, lớp SomeImpl sẽ được khởi tạo, và cùng một cá thể sẽ được đưa vào thể hiện SomeServlet. Như đã đề cập trước đây, servlets bị ràng buộc với câu lệnh "serve ... with ..." cũng dường như được khởi tạo một cách hăng hái, nhưng dù cách nào thì vẫn chỉ có một đối tượng SomeImpl được khởi tạo. Tuy nhiên, vì một lý do nào đó, tôi có hai đối tượng SomeImpl được khởi tạo khi thực hiện điều này. Để có được xung quanh nó, tôi trộn hai dòng trong configure() một chút, và thay vào đó những điều trên tôi đã có những dòng sau:

bind(SomeImpl.class).in(Singleton.class) 
bind(SomeInterface.class).to(SomeImpl.class).asEagerSingleton(); 

và sau đó nó làm việc tốt, và tôi đã nhận chỉ có một thể hiện của SomeImpl đã khởi tạo.Tôi không thực sự hiểu tại sao switch lại quan trọng - tôi có thể thấy cách thứ hai là "tốt hơn", nhưng tôi hy vọng cả hai sẽ hoạt động chính xác, vì vậy tôi chỉ tự hỏi liệu tôi có gặp vấn đề gì ở đây không .. ?



Xin lỗi về độ dài,
Cảm ơn sự trợ giúp!

Trả lời

7

1) Không có cách nào để tránh điều này, vì Guice gọi phương thức init() của tất cả các servlet khi khởi tạo đường dẫn bộ lọc riêng và do đó xây dựng tất cả chúng. Nếu bạn thực sự cần logic khởi tạo lười biếng như vậy, bạn nên đặt nó vào chính servlet (hoặc sử dụng một lớp trợ giúp tách rời, hoặc ... có nhiều cách, tùy thuộc vào trường hợp sử dụng của bạn).

2) Nói chung, các mô-đun của Guice tuyên bố ràng buộc, không được thiết kế để trở thành định nghĩa khởi động với các đơn đặt hàng tức thời chính xác. Nếu bạn cần một thứ tự khởi tạo được xác định như vậy, hãy tự tạo các đối tượng theo thứ tự mong muốn và liên kết chúng thông qua bind(...).toInstance(...). Nếu bạn cần tiêm trong các trường hợp tự xây dựng, bạn có thể sử dụng requestInjection(...) (nếu trường/phương pháp tiêm là đủ, nó cồng kềnh hơn cho việc xây dựng tiêm).

3) Phạm vi của Guice áp dụng cho khóa ràng buộc, không phải giá trị ràng buộc, Applying Scopes mô tả lý do tại sao chỉ ví dụ thứ hai của bạn hoạt động như dự định.