Guice:如何基于(动态Web属性)在运行时更改注入 [英] Guice: How to change injection on runtime based on a (dynamic web property)

查看:105
本文介绍了Guice:如何基于(动态Web属性)在运行时更改注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是我面临的问题的近似值。

The following is an approximation of the problem I'm facing.

认为我们有一个带有某些规则的密码验证器。

Think we have a password validator with some rules.

public interface RuleChecker{

    //Checks for a password strenght, returns 10
    //for strong or 0 for soft password.
    int check(String pass);
}

然后我们有几种实现,我们的服务将仅接受密码得分超过8。

And then we have several implementations, our service will only accept the password if it is over 8 score.

public class NoCheck implements RuleChecker {
    public int check(String pass){return 10;}
}

public class LengthCheck implements RuleChecker{
    ...
}
public class AlphanumericCheck implements RuleChecker{
    ...
}
public class AlphaAndLenghtCheckAdapter implements RuleChecker{
    ...
}

但是出于测试目的,我们希望在应用程序中实现一个Web服务,在这里我们可以管理这些规则,并选择要包含的规则。

But for testing purposes, we want to implement a webservice within the application where we can "admin" those rules, and select which ones to have.

public class PasswordCheckService{

     private RuleChecker checker;

     @Inject
     public PasswordCheckService(final RuleChecker checker){
         this.checker = checker;
     }

     public boolean checkPassword(String password){
         return checker.check(password) > 8;
     }
}

因此,Guice有什么办法可以改变在运行时,服务具有注入吗?

So, is there any way in Guice, to change at runtime, the injection a service has?

示例:

我们启动了应用程序,默认情况下,LengthCheck为选择并注入到应用程序中,在网站上,我们选择NoCheck复选框并保存选项,该选项存储在数据库中,我是否可以配置Guice自动更改以前注入服务的bean?所以从现在开始,将不再检查新密码吗?

We started the application and by default LengthCheck is selected and injected on the application, at the website we select the NoCheck checkbox and save options, which is stored into the database, can I configure Guice to automatically change the bean the service had injected before? so from now and on there will be no checks on new passwords?

-

就目前而言,我已经找到了这些主题

As for now, I have found those topics

Google Guice和运行时的各种注入方式
但我不知道这种提供程序是否适合我的问题。

Google Guice and varying injections at runtime But i dont know if that kind of providers fits my problem.

Guice运行时依赖项参数重新注入
这个好问题是在讲类似的东西,但不是我在说什么

Guice runtime dependency parameters reinjection That nice question is talking something similar, but not what I'm looking form.

guice:在命令行中运行时注入/绑定
这是最接近我的问题,但他只在启动运行时时才会这样做,并且不会随时间更改它。

guice: runtime injection/binding at command line This is the closest to my problem but he only does on starting "runtime" and does not change it over the time.

有帮助吗?

谢谢!

使用我实现了此POC的第一个注释的提示,但仍然无法使用,如果更改选择另一个按钮,则服务Bean不会更新。
https://bitbucket.org/ramonboza/guicedynamicconfig

Using the tip of the first comment I implemented this POC but still does not works, if you change select another button the service bean is not updated. https://bitbucket.org/ramonboza/guicedynamicconfig

推荐答案

为每种字段类型(登录,密码,出生日期...)创建提供程序,并使用参数将实现更改为返回。

Create a provider for each field type (login, password, birth date...), with a parameter to change the implementation to return.

public class MyModule extends AbstractModule {

    public void configure() {
       bind(RuleChecker.class).annotatedWith(named("password")).toProvider(PasswordRuleCheckerProvider.class);
       bind(RuleChecker.class).annotatedWith(named("login")).toProvider(LoginRuleCheckerProvider.class);
    }
}

public static class PasswordRuleCheckerProvider implements Provider<RuleChecker> {

    private static CheckType type = CheckType.ALPHANUMERIC;
    // static type setter.

    public RuleChecker get() {
        // it would even be better if you could use singletons here.
        switch(type) {
            case LENGTH:
                return new LengthCheck();
            case ALPHANUMERIC:
                return new AlphanumericCheck();
            case ALPHALENGTH:
                return new AlphaAndLenghtCheckAdapter();
            case NONE:
            default:
                return NoCheck();
        }
    }
}
// Almost same provider for your LoginRuleCheckerProvider. You could do something generic.

在您的管理部分中,您更改了类型值,因此您的规则也会更改。由于有注释,它可能会影响有限的字段集。例如: PasswordRuleCheckerProvider.setType(CheckType.LENGTH); 。只会影响具有 @Named('password')的字段。

In your admin section you change "type" value, so your rules will change. It can affect a limited set of fields, thanks to the annotations. For instance : PasswordRuleCheckerProvider.setType(CheckType.LENGTH);. Will only affect fields with @Named('password').

您必须声明字段和服务,例如

You have to declare your fields and services like this :

public abstract class DynamicService {
    protected void updateService() {
        // Reinject with the new implementations the members.
        App.getInjector().injectMembers(this);
    }
}

public class PasswordCheckService extends DynamicService  {
    @Inject
    @Named("password")
    private RuleChecker passwordChecker;

    public void changePasswordCheckType(CheckType type) {
        PasswordRuleCheckerProvider.setType(type);
        // Reinject, so you have your new implementation.
        updateService();
    }

    // [...]
}

这篇关于Guice:如何基于(动态Web属性)在运行时更改注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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