简体   繁体   English

更改参数的Guice配置

[英]Change Guice Configuration on Parameter

Lets say I have a class that verifies passwords according to a set of rules. 可以说我有一个根据一组规则验证密码的类。 How exactly this password is verified, depends on the person that calls the server. 验证密码的确切方式取决于调用服务器的人员。 Each different kind of person has a different implementation for some rules. 对于某些规则,每种不同的人都有不同的实现。 Lets say the LengthRule would requiere a length of 12 in a strict validation 8 in a normal validation and 5 in a lax validation. 假设LengthRule在严格验证中需要12的长度,在正常验证中需要8,在宽松验证中需要5。
What is the best way to change the binding of all rules according to the passed parameter , for example group wirings and switch them dynamically? 根据传递的参数更改所有规则的绑定的最佳方法是什么 ,例如组布线并动态切换它们?

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

this is an answer based on MultiBindings in guice. 这是基于guice中MultiBindings的答案。 General: You can bind multiple implementations to a given interface and then inject a set of implementations. 常规:您可以将多个实现绑定到给定的接口,然后注入一组实现。

What I am going to do is to bind all my Password checkers, inject them and then use that set to determine what to do. 我要做的是绑定我所有的密码检查器,注入它们,然后使用该设置确定要做什么。

This is the complete running example: 这是完整的运行示例:

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

The Test class is your example. Test类就是您的示例。 It takes a password and a Person enum. 它需要一个密码和一个Person枚举。

Each PasswordChecker implements a method called "isApplicable" to determine if the given Person can use this checker. 每个PasswordChecker都实现一种称为“ isApplicable”的方法,以确定给定的Person是否可以使用此检查器。 Alternatively, at injection time, you could map the PasswordChecker to the correct person (using the stream.collect(Collectors.toMap(...)) methods). 另外,在注入时,您可以将PasswordChecker映射到正确的人(使用stream.collect(Collectors.toMap(...))方法)。 That way you would only have to do a hashmap lookup to get the correct implementation. 这样,您只需执行哈希图查找即可获得正确的实现。

In my module, I define a multibinding for password checkers. 在我的模块中,我为密码检查器定义了多重绑定。 I add my bindings to it. 我将绑定添加到它。

The rest you can see. 其余的您可以看到。

Calling my code will print: 调用我的代码将打印:

User Business Checker
User Client Checker

I hope this is what you were looking for :) let me know! 我希望这就是您想要的:)让我知道!

Artur 阿图尔

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM