How to inject an interface implementation based on annotations at runtime using Google Guice
我有以下情况:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public interface ServiceClientAdapter { SomeData getSomeData() } @LegacyServiceClientAdapter public class MyLegacyServiceClientAdapterImpl implements ServiceClientAdapter { public SomeData getSomeData() { // implementation } } @NewServiceClientAdapter public class MyNewServiceClientAdapterImpl implements ServiceClientAdapter { public SomeData getSomeData() { // implementation } } public class BusinessLogic { @Inject private ServiceClientAdapter serviceClientAdapter; } |
LegacyServiceClientAdapter和NewServiceClientAdapter是自定义注释。
serviceClientAdapter字段的实现将在运行时根据用户是否已从旧版迁移到新服务来
使用Google Guice完成此依赖项注入的最佳方法是什么?
考虑到将存在不同的BusinessLogic类,每个类都具有自己的(不同的)类似于ServiceClientAdapter的接口以及相应的旧版和新实现类。
理想情况下,这应该使用可在所有用例中使用的一段框架代码来完成。
我将假设LDAP调用的结果可以表示为字符串,例如
在您的模块中,使用MapBinder:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public class BusinessLogicModule { @Override protected void configure() { // create empty map binder MapBinder<String, ServiceClientAdapter> mapBinder = MapBinder.newMapBinder( binder(), String.class, ServiceClientAdapter.class); // bind different impls, keyed by descriptive strings mapBinder.addBinding("legacy") .to(MyLegacyServiceClientAdapterImpl.class); mapBinder.addBinding("new") .to(MyNewServiceClientAdapterImpl.class); } } |
现在,您可以将实例映射(如果需要继续创建新实例,则可以注入实例提供者的映射)到您的主类中,并使用在运行时发现的字符串来控制您获得哪种类型的实例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class BusinessLogic { @Inject private ServiceClientAdapter serviceClientAdapter; @Inject private Map<String, ServiceClientAdapter> mapBinder; public void setupAndUseClientAdapter() { String userType = getUserTypeFromLdapServer(); serviceClientAdapter = mapBinder.get(userType); if (serviceClientAdapter == null) { throw new IllegalArgumentException( "No service client adapter available for" + userType +" user type."; } doStuffWithServiceClientAdapter(); } } |