Tạo chú thích của riêng bạn được sử dụng để trang trí các biến mẫu hoặc phương thức setter, sau đó một bộ xử lý hậu xử lý chú thích và tiêm một proxy chung để giải quyết việc triển khai chính xác khi chạy và ủy quyền cuộc gọi.
@Component
public class TransactionService {
@LocalizedResource
private TransactionRules rules;
//..
}
@Retention(RUNTIME)
@Target({FIELD, METHOD})
public @interface LocalizedResource {}
Dưới đây là các thuật toán cho postProcessBeforeInitialization(bean, beanName)
phương pháp trong đậu sau xử lý của bạn:
- nội quan lớp bean để tìm ra các biến dụ hoặc các phương pháp setter được chú thích với @LocalizedResource. Lưu trữ kết quả trong bộ nhớ đệm (chỉ một bản đồ) được lập chỉ mục theo tên lớp. Bạn có thể sử dụng số
InjectionMetadata
của Spring cho mục đích này.Bạn có thể tìm các ví dụ về cách nó hoạt động bằng cách tìm kiếm các tham chiếu đến classe này trong mã mùa xuân.
- Nếu trường hoặc phương thức như vậy tồn tại đối với bean, hãy tạo proxy bằng cách sử dụng InvocationHandler được mô tả bên dưới, chuyển nó qua BeanFactory hiện tại (trình xử lý hậu đậu phải là ApplicationContextAware). Tiêm proxy đó trong biến cá thể, hoặc gọi phương thức setter với cá thể proxy.
Đây là InvocationHandler cho proxy sẽ được sử dụng để tạo tài nguyên được bản địa hóa.
public class LocalizedResourceResolver implements InvocationHandler {
private final BeanFactory bf;
public LocalizedResourceResolver(BeanFactory bf) {
this.bf = bf;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String locale = lookupCurrentLocale();
Object target = lookupTarget(locale);
return method.invoke(target, args);
}
private String lookupCurrentLocale() {
// here comes your stuff to look up the current locale
// probably set in a thread-local variable
}
private Object lookupTarget(String locale) {
// use the locale to match a qualifier attached to a bean that you lookup using the BeanFactory.
// That bean is the target
}
}
Bạn có thể cần thực hiện thêm một số điều khiển đối với loại bean hoặc thêm loại bean được yêu cầu trong InvocationHandler.
Điều tiếp theo là tự động phát hiện các giao diện đã cho, phụ thuộc vào địa phương và đăng ký chúng với bộ định danh tương ứng với ngôn ngữ. Bạn có thể triển khai BeanDefinitionRegistryPostProcessor
hoặc BeanFactoryPostProcessor
cho mục đích đó, để thêm BeanDefinition
s mới vào sổ đăng ký, với trình độ đủ điều kiện, một cho mỗi triển khai giao diện nhận thức miền địa phương. Bạn có thể đoán miền địa phương của một triển khai bằng cách làm theo các quy ước đặt tên: nếu một giao diện nhận biết miền địa phương được gọi là TransactionRules, thì việc triển khai có thể được đặt tên là TransactionRules_ISOCODE trong cùng một gói.
Nếu bạn không có khả năng đặt tên quy ước, bạn sẽ cần phải có một số loại quét đường dẫn + một cách để đoán miền địa phương của một triển khai nhất định (có thể là chú thích trên lớp triển khai). Quét Classpath là có thể nhưng khá phức tạp và chậm, vì vậy hãy thử để tránh nó.
Dưới đây là một bản tóm tắt về những gì sẽ xảy ra:
- Khi ứng dụng khởi động, triển khai các TransactionRules sẽ được phát hiện và định nghĩa bean sẽ được tạo cho mỗi người trong số họ, với khuôn khổ vòng loại tương ứng với miền địa phương của mỗi thực hiện . Tên đậu cho những hạt cà phê này không có liên quan như tra cứu được thực hiện dựa trên loại và vòng loại.
- Trong khi thực thi, hãy đặt ngôn ngữ hiện tại trong biến địa chỉ
- Tra cứu bean bạn cần (ví dụ: TransactionService). Post-processor sẽ tiêm một proxy cho mỗi trường instance @LocalizedResource hoặc phương thức setter.
- Khi gọi phương thức trên TransactionService kết thúc thành một số phương thức TransactionRules, trình xử lý yêu cầu được liên kết với proxy chuyển sang triển khai chính xác dựa trên giá trị được lưu trữ trong biến thread-local, sau đó ủy quyền cuộc gọi đến thực hiện đó.
Không thực sự nhỏ, nhưng nó hoạt động. Đây thực sự là cách @PersistenceContext được xử lý bởi Spring, ngoại trừ việc tra cứu triển khai, đây là một tính năng bổ sung của trường hợp sử dụng của bạn.
Bây giờ trong năm 2017, không có cách nào đơn giản hơn để đạt được điều này? – maxxyme