java - 更改 Guice 参数配置

标签 java dependency-injection guice

假设我有一个类,它根据一组规则验证密码。该密码的验证方式取决于调用服务器的人。每个不同类型的人对某些规则都有不同的实现。假设 LengthRule 在严格验证中要求长度为 12,在正常验证中要求长度为 8,在宽松验证中要求长度为 5。
根据传递的参数更改所有规则的绑定(bind)的最佳方法是什么,例如分组接线并动态切换它们?

public void verifyPassword(String password, Person person) {
    if (isBusinessClient(person)) {
            // Apply strict wiring  
            PasswordChecker checker = new PasswordChecker();
            passwordChecker.check(password)
    } else if (wasBusinessClient(person)) {
            // Apply normal wiring 
            PasswordChecker checker = new PasswordChecker();
            passwordChecker.check(password)
    } else {
            // Apply lax wiring
            PasswordChecker checker = new PasswordChecker();
            passwordChecker.check(password)
    }
}

最佳答案

这是基于 guice 中的 MultiBindings 的答案。一般:您可以将多个实现绑定(bind)到给定接口(interface),然后注入(inject)一组实现。

我要做的是绑定(bind)所有密码检查器,注入(inject)它们,然后使用该组来确定要做什么。

这是完整的运行示例:

public class TestMultiBinding {

    public static void main(String[] args) {

        Injector injector = Guice.createInjector( new AbstractModule() {

            @Override
            protected void configure() {
                Multibinder<PasswordChecker> multiBinder = Multibinder.newSetBinder(binder(), PasswordChecker.class);
                multiBinder.addBinding().to(BusinessChecker.class);
                multiBinder.addBinding().to(ClientChecker.class);

                bind(Test.class).in(Singleton.class);
            }
        });


        Test test = injector.getInstance(Test.class);
        test.verifyPassword("hello", Person.P1);
        test.verifyPassword("hello", Person.P2);
    }

    public static class Test {

        private Set<PasswordChecker> checkers;

        @Inject
        public Test(final Set<PasswordChecker> checker) {
            this.checkers = checker;
        }

        public void verifyPassword(final String pass, final Person p) {
            getPasswordChecker(p).check(pass);
        }

        public PasswordChecker getPasswordChecker(final Person p) {
            Optional<PasswordChecker> checker = checkers.stream().filter(c -> c.isApplicable(p)).findFirst();
            if(checker.isPresent()) {
                return checker.get();
            }
            return null; // or default
        }
    }


    public static interface PasswordChecker {
        public void check(String s);
        boolean isApplicable(Person P);
    }

    public static class BusinessChecker implements PasswordChecker {

        @Override
        public void check(String s) {
            System.out.println("User Business Checker");
        }

        @Override
        public boolean isApplicable(Person P) {
            return P.equals(Person.P1);
        }
    }

    public static class ClientChecker implements PasswordChecker {

        @Override
        public void check(String s) {
            System.out.println("User Client Checker");
        }

        @Override
        public boolean isApplicable(Person P) {
            return P.equals(Person.P2);
        }
    }

    public enum Person {
        P1, P2;
    }
}

测试类是您的示例。它需要一个密码和一个 Person 枚举。

每个PasswordChecker 都实现一个名为“isApplicable”的方法来确定给定的Person 是否可以使用此检查器。或者,在注入(inject)时,您可以将PasswordChecker映射到正确的人(使用stream.collect(Collectors.toMap(...))方法)。这样您只需进行 HashMap 查找即可获得正确的实现。

在我的模块中,我为密码检查器定义了多重绑定(bind)。我将我的绑定(bind)添加到其中。

其余的你可以看到。

调用我的代码将打印:

User Business Checker
User Client Checker

我希望这就是您正在寻找的:)请告诉我!

阿图尔

关于java - 更改 Guice 参数配置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39104439/

相关文章:

java - 具有未知对象结构的标准根元素的遍历路径

java - 如果它不是 'dynamic web app',如何在 eclipse 中对 Tomcat 运行 WAR?

java - 非目标绑定(bind)与 `toInstance()` 绑定(bind)

java - Guice 是否支持方法注入(inject)(非 setter 注入(inject))?

java - 如何使用 Github API 列出所有 Github android 项目?

javascript - 自定义图像服务和 native 图像元素构造函数之间的冲突

java - Micronaut:从上下文获取 bean 的问题

java - hibernate validator : Intercept Invalid Values

java - Guice 可以根据一个参数自动创建不同类的实例吗?

java - 两个时区之间的总飞行时间?