Java 如何使用GoogleGuice在运行时注入基于注释的接口实现
我有以下情况:Java 如何使用GoogleGuice在运行时注入基于注释的接口实现,java,dependency-injection,guice,Java,Dependency Injection,Guice,我有以下情况: public interface ServiceClientAdapter { SomeData getSomeData() } @LegacyServiceClientAdapter public class MyLegacyServiceClientAdapterImpl implements ServiceClientAdapter { public SomeData getSomeData() { // implementation
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字段的实现将在运行时由用户是否已从旧服务迁移到新服务来确定
使用GoogleGuice实现依赖注入的最佳方法是什么
考虑到将存在不同的BusinessLogic类,每个类都有自己的(不同的)ServiceClientAdapter类接口以及相应的旧实现类和新实现类
理想情况下,这应该通过一段可以在所有用例中使用的框架代码来完成。我假设LDAP调用的结果可以表示为字符串,比如说
“legacy”
或“new”
。如果没有,希望您仍然能够适应此示例
在您的模块中,使用:
公共类BusinessLogicModule{
@凌驾
受保护的void configure(){
//创建空地图活页夹
MapBinder MapBinder=
MapBinder.newMapBinder(
binder()、String.class、ServiceClientAdapter.class);
//绑定不同的impl,由描述性字符串键入
mapBinder.addBinding(“遗留”)
.to(MyLegacyServiceClientAdapterImpl.class);
mapBinder.addBinding(“新”)
.to(MyNewsServiceClientAdapterImpl.class);
}
}
现在,您可以将实例映射(或实例提供者映射,如果您需要继续创建新实例)注入到主类中,并使用运行时发现的字符串来控制获得的实例类型
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();
}
}
公共类业务逻辑{
@注入
私人服务客户端适配器服务客户端适配器;
@注入
私人地图装订机;
公共无效设置和使用客户端适配器(){
字符串userType=getUserTypeFromLdapServer();
serviceClientAdapter=mapBinder.get(用户类型);
如果(serviceClientAdapter==null){
抛出新的IllegalArgumentException(
“没有可用于的服务客户端适配器”+
用户类型+“用户类型。”;
}
doStuffWithServiceClientAdapter();
}
}
如何确定用户是否已迁移?是否检查了系统属性或其他内容?将通过调用LDAP服务器(稍后将缓存)来确定。正在以泛型方式实现此功能,但出现以下错误:java.util.Map不能用作键;它未完全指定。我是否应确保所有ServiceClientAdapter都实现根接口?或者是否有某种方法使用TypeLiteral来允许泛型?以及如何使用提供程序类而不是是否包含对LDAP服务器的调用?@rudolfv如果没有看到您的代码,我无法猜测映射错误来自何处,尤其是因为我不确定您为什么试图使用Impl类作为映射的键。@rudolfv映射绑定器不包含对LDAP服务器的调用,它包含一个基于结果的决策映射如果你想在你的类中使用impl提供程序,只需@injectmap mapBinder
而不是我上面所说的,然后调用mapBinder.get(userType).get()
而是获得一个干净的实例。不需要对模块进行任何更改。关键是AdapterImplType,它是一个枚举。但我同意,在没有看到代码的情况下,您很难伸出援手。我成功地获得了一个运行的解决方案,只有一个提供程序,没有MapBinder。原因是我正在运行Weblogic 10.3.6 EJB(J2EE 5),这迫使我以某种方式引导GUI。我还有一个限制,我希望LDAP查找代码位于中心位置,而不是BusinessLogic EJB的实现者甚至应该知道的东西。如果您想看看,我可以创建Git repo?
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();
}
}