更改绑定吉斯在运行时 [英] Changing Guice bindings at runtime

查看:165
本文介绍了更改绑定吉斯在运行时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望能够改变注射吉斯在运行时,支持基于用户输入多次注射。这就是我想达到什么样的:

 公共接口IDao {
    公众诠释的someMethod();
}公共类DaoEarth实现IDao {
    @覆盖
    公众诠释的someMethod(){...}
}公共类DaoMars实现IDao {
    @覆盖
    公众诠释的someMethod(){...}
}公共类MyClass的{
    @注入
    私人IDao myDao;    公众诠释myMethod的(字符串域){
        //如果域==地球,myDao应该是类型DaoEarth的        //如果域== DaoMars,myDao应该是类型DaoMars的
    }
}

我的想法写我自己的提供者,但我不知道如何使用供应商在运行时改变我的绑定。任何投入是值得欢迎和AP preciated:!)

更新
这是我目前想到了,它并不像pretty因为我想,所以我还在寻找反馈

 公共类DomainProvider {
    @Inject @Earth
    私人IDaoProvider earthDaoProvider;    @Inject @Mars
    私人IDaoProvider marsDaoProvider;    公共IDaoProvider GET(域域){
        开关(域){
            案例地球:
                返回earthDaoProvider;
            案例MARS:
                返回marsDaoProvider;
        }
    }    公共IDaoProvider GET(字符串域){
        域parsedDomain = Domain.valueOf(domain.toUpperCase());
        得到的回报(parsedDomain);
    }
}// MarsDaoProvider将相当于
公共类EarthDaoProvider实现IDaoProvider {
    @Inject @Earth
    私人IDao earthDao;    公共IDao getDao(){
        返回earthDao;
    }
}这意味着在MyClass的,我可以这样做:
公共类MyClass的{
    @注入
    私人DomainProvider domainProvider;    公众诠释myMethod的(字符串域){
        IDaoProvider daoProvider = domainProvider.get(域);
        IDao道= daoProvider.getDao();        //现在道将基于域是正确的类型
    }
}//当然,其他地方我都绑定设置类似
绑定(IDao.class).annotatedWith(Earth.class)。为了(EarthDao.class);


解决方案

您的版本几乎是完美的,因为它是:你将需要注入某种对象返回基于code一方或另一方的你写的,并且不需要辅助注射或类似的东西。这就是说,你可以跳过一些样板的:

 公共类DomainProvider {
    //只是直接注入供应商没有明确约束他们。
    @Inject @Earth提供商LT; IDao> earthDaoProvider;
    @Inject @Mars提供商LT; IDao> marsDaoProvider;    公共提供商LT; IDao>得到(域域){
        开关(域){
            案例地球:
                返回earthDaoProvider;
            案例MARS:
                返回marsDaoProvider;
        }
    }    公共提供商LT; IDao>得到(字符串域){
        域parsedDomain = Domain.valueOf(domain.toUpperCase());
        得到的回报(parsedDomain);
    }
}

您在这种情况下MyClass的是完全相同。在这里,提供或者是一个方法泛型接口的 com.google.inject.Provider ,或相当于内置的 javax.inject.Provider 它延伸。了解更多关于相关吉斯维基话题

 绑定(IDao.class).annotatedWith(Earth.class)。为了(EarthDao.class);
//现在可以注入@Earth IDao,也是@Earth提供商LT; IDao>中。

基本上,如果你绑定一个键(一类,供应商, @Provides 方法,或实例),你自动获得注入无论是提供商LT;富> 没有额外的工作。供应商也确保你得到一个新实例每次调用 GET 一个伟大的方式;与原来的,您总能获得EarthDao或MarsDao的同一个实例对于任何给定DomainProvider你注入。

这意味着你可以跳过自定义EarthDaoProvider和MarsDaoProvider,除非你真的需要在执行任何外部初始化它们,此时你可能会更好调用绑定(EarthDao.class)。 toProvider(EarthDaoProvider.class)所以直接注射EarthDao时preparation也会发生。你也可以只具备DomainProvider直接调用 GET 上相应的提供者返回IDao实例,放心,它每一次将是一个新的实例。

I would like to be able to change the Guice injections at runtime to support multiple injections based on user input. This is what I would like to achieve:

public interface IDao {
    public int someMethod();
}

public class DaoEarth implements IDao {
    @Override
    public int someMethod(){ ... }
}

public class DaoMars implements IDao {
    @Override
    public int someMethod(){ ... }
}

public class MyClass {
    @Inject
    private IDao myDao;

    public int myMethod(String domain) {
        //If Domain == Earth, myDao should be of the type DaoEarth

        //If Domain == DaoMars, myDao should be of the type DaoMars
    }
}

I was thinking of writing my own Provider, but I don't know how to use that provider to change my bindings at runtime. Any input is welcome and appreciated :)!

Update Here's what I currently came up with, it's not as pretty as I'd like, so I'm still looking for feedback

public class DomainProvider {
    @Inject @Earth
    private IDaoProvider earthDaoProvider;

    @Inject @Mars
    private IDaoProvider marsDaoProvider;

    public IDaoProvider get(Domain domain){
        switch (domain){
            case EARTH:
                return earthDaoProvider;
            case MARS:
                return marsDaoProvider;
        }
    }

    public IDaoProvider get(String domain){
        Domain parsedDomain = Domain.valueOf(domain.toUpperCase());
        return get(parsedDomain);
    }
}

//MarsDaoProvider would be equivalent
public class EarthDaoProvider implements IDaoProvider {
    @Inject @Earth
    private IDao earthDao;

    public IDao getDao() {
        return earthDao;
    }
}

This means that in "MyClass", I can do:
public class MyClass {
    @Inject
    private DomainProvider domainProvider;

    public int myMethod(String domain) {
        IDaoProvider daoProvider = domainProvider.get(domain);
        IDao dao = daoProvider.getDao();

        //Now "dao" will be of the correct type based on the domain
    }
}

//Of course elsewhere I have the bindings set like
bind(IDao.class).annotatedWith(Earth.class).to(EarthDao.class);

解决方案

Your version is almost perfect as it is: You're going to need to inject some kind of object that returns one or the other based on code you write, and don't need assisted injection or anything like that. That said, you can skip some of the boilerplate:

public class DomainProvider {
    // Just inject Providers directly without binding them explicitly.
    @Inject @Earth Provider<IDao> earthDaoProvider;
    @Inject @Mars Provider<IDao> marsDaoProvider;

    public Provider<IDao> get(Domain domain){
        switch (domain){
            case EARTH:
                return earthDaoProvider;
            case MARS:
                return marsDaoProvider;
        }
    }

    public Provider<IDao> get(String domain){
        Domain parsedDomain = Domain.valueOf(domain.toUpperCase());
        return get(parsedDomain);
    }
}

Your MyClass in that case would be exactly identical. Here, Provider is either the one-method generic interface com.google.inject.Provider, or the equivalent builtin javax.inject.Provider that it extends. Read more about Guice Providers on the relevant Guice wiki topic.

bind(IDao.class).annotatedWith(Earth.class).to(EarthDao.class);
// You can now inject "@Earth IDao" and also "@Earth Provider<IDao>".

Basically, if you bind a key Foo (to a class, provider, @Provides method, or instance), you automatically get to inject either a Foo or Provider<Foo> with no additional work. Providers are also a great way to ensure that you get a new instance with every call to get; with your original, you'll always get the same instance of EarthDao or MarsDao for any given DomainProvider you inject.

This means you can skip your custom EarthDaoProvider and MarsDaoProvider, unless you really need to perform any external initialization on them—at which point you'd probably be better off calling bind(EarthDao.class).toProvider(EarthDaoProvider.class) so the preparation also happens when injecting EarthDao directly. You could also just have DomainProvider return an IDao instance directly by calling get on the appropriate Provider, and be assured that it'll be a new instance every time.

这篇关于更改绑定吉斯在运行时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆