web-dev-qa-db-ja.com

Guice :(動的ウェブプロパティ)に基づいて実行時にインジェクションを変更する方法

以下は私が直面している問題の概算です。

いくつかのルールを備えたパスワードバリデーターがあると考えてください。

public interface RuleChecker{

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

そして、いくつかの実装があります。私たちのサービスは、8スコアを超える場合にのみパスワードを受け入れます。

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サービスを実装し、ルールを選択する必要があります。

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には、実行時に変更する方法がありますか?サービスにインジェクションがありますか?

例:

アプリケーションを起動し、デフォルトでLengthCheckが選択されてアプリケーションに注入されます。ウェブサイトで、NoCheckチェックボックスを選択し、データベースに保存されているオプションを保存します。サービスが以前に注入したBeanを自動的に変更するようにGuiceを構成できますか?それで、これからは新しいパスワードのチェックはありませんか?

-

今のところ、私はそれらのトピックを見つけました

Google Guiceと実行時のさまざまなインジェクション しかし、その種のプロバイダーが私の問題に適合するかどうかはわかりません。

Guiceランタイム依存関係パラメーターの再注入 その素晴らしい質問は似たようなことを話しているが、私が探しているものではない。

guice:コマンドラインでのランタイムインジェクション/バインディング これは私の問題に最も近いですが、彼は「ランタイム」の開始時にのみ実行し、時間の経過とともに変更しません。

何か助けはありますか?

ありがとうございました!

最初のコメントのヒントを使用して、このPOCを実装しましたが、それでも機能しません。別のボタンを選択して変更すると、サービスBeanは更新されません。 https://bitbucket.org/ramonboza/guicedynamicconfig

11
RamonBoza

各フィールドタイプ(ログイン、パスワード、生年月日など)のプロバイダーを作成し、返される実装を変更するパラメーターを指定します。

_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')のフィールドにのみ影響します。

このようにフィールドとサービスを宣言する必要があります:

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

    // [...]
}
_