如何使用Google Guice在运行时基于注释注入接口实现

时间:2014-08-23 09:50:59

标签: java dependency-injection guice

我有以下情况:

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的接口以及相应的旧版和新版实现类。

理想情况下,这应该通过一个可以在所有用例中使用的框架代码来完成。

1 个答案:

答案 0 :(得分:1)

我将假设您的LDAP调用结果可以表示为字符串,例如"legacy""new"。如果没有,希望你仍然能够适应这个例子。

在您的模块中,使用MapBinder

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);
    }
}

现在,您可以将实例映射(或实例提供程序的映射,如果需要继续创建新实例)注入主类,并使用在运行时发现的字符串来控制您获得的实例类型。

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();
    }
}