Một lựa chọn sẽ được tiêm một Provider<InjectedObject>
vào lớp học của bạn, như Jesse nói:
public class MyClass {
private final List<InjectedObject> injectedObjects;
@Inject
public MyClass(Provider<InjectedObject> injectedObjectProvider) {
List<InjectedObject> objects = new ArrayList<InjectedObject>();
for (int i = 0; i < 5; i++) {
objects.add(injectedObjectProvider.get());
}
injectedObjects = Collections.unmodifiableList(objects);
}
}
Việc làm này có thể có vấn đề . Nếu InjectedObject
có phạm vi @Singleton
hoặc @RequestScoped
, thì mỗi lần bạn gọi injectedObjectProvider.get()
bạn sẽ nhận được cùng một tham chiếu. Một vấn đề khác khi tiêm một Provider
để làm điều này là nó sẽ không được rõ ràng từ API mà MyClass
phụ thuộc vào nhiều trường hợp của InjectedObject. Cuối cùng, bạn đã hardcoded trong MyClass
rằng nó cần phải được tiêm với năm trường hợp.
Rất hiếm khi bạn cần phải tiêm Provider
vào một đối tượng. Thông thường khi tôi làm điều này, đó là vì phạm vi của đối tượng hiện tại có nghĩa là nó sẽ tồn tại lâu hơn phạm vi của đối tượng phụ thuộc (ví dụ: @Singleton
cần truy cập đối tượng @RequestScoped
).
Thay vì tiêm một Provider
, bạn có thể tiêm một List<InjectedObject>
vào constructor, và tạo ra một phương pháp cung cấp dịch vụ trong một module Guice:
@Provides
MyClass prividesMyClass(Provider<InjectedObject> injectedObjectProvider) {
List<InjectedObject> objects = new ArrayList<InjectedObject>();
for (int i = 0; i < 5; i++) {
objects.add(injectedObjectProvider.get());
}
return new MyClass(objects);
}
(bạn có thể, tất nhiên, ràng buộc sử dụng một TypeLiteral
)
Tại sao điều này lại tốt hơn? Mặc dù bạn vẫn còn mã hóa cứng năm đối tượng trong mã này, nhưng nó không được mã hóa cứng trong MyClass
, vì vậy các máy khách của MyClass
(bao gồm các bài kiểm tra cho chính mình là MyClass
) có thể chọn xây dựng đối tượng theo các cách khác nhau.
Nếu cứng mã hóa kiến thức này trong một module Guice không phải là một ý tưởng tốt, bạn thay vì có thể tạo ra một giao diện mà có một hợp đồng cụ thể hơn Provider
public interface InjectedObjectRepository {
List<InjectedObject> getInjectedObjects();
}
Thậm chí nếu bạn quyết định rằng bạn muốn MyClass
chịu trách nhiệm về việc biết có bao nhiêu trường hợp để tạo, bạn có thể muốn tạo một giao diện (có thể là InjectedObjectSupplier
để bạn có thể ghi rõ ràng rằng bạn mong đợi một cá thể duy nhất mỗi lần.
Cảm ơn đã gợi ý - lý do có nhiều quy háo hức được để có thể đặt chúng vào một ThreadPool - số lượng các cá thể trong nhóm sẽ phụ thuộc vào số lượng lõi có sẵn. – Rich
Bạn sẽ làm như thế nào nếu bạn không có quyền kiểm soát mã nguồn MyClass, nhưng chỉ muốn tiêm nó bằng cách sử dụng các ràng buộc và mã khác trong cấu hình Module (Tốt hơn là không sử dụng Multibindings vì nó không tương thích với Gin)? – Snekse
Snekse, bạn có thể tạo phương thức @Provides lấy Nhà cung cấp làm tham số và gọi hàm dựng MyClass ở cuối. –