更改参数的 Guice 配置
Change Guice Configuration on Parameter
假设我有一个 class 可以根据一组规则验证密码。如何准确验证此密码取决于调用服务器的人。每个不同类型的人对某些规则都有不同的实现。假设 LengthRule 在严格验证中要求长度为 12,在正常验证中要求长度为 8,在宽松验证中要求长度为 5。
根据传递的参数更改所有规则绑定的最佳方法是什么,例如分组布线并动态切换它们?
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 的答案。一般:您可以将多个实现绑定到给定接口,然后注入一组实现。
我要做的是绑定我所有的密码检查器,注入它们,然后使用该组来确定要做什么。
这是完整的 运行 示例:
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;
}
}
测试 class 就是你的例子。它需要一个密码和一个 Person 枚举。
每个 PasswordChecker 实现一个名为 "isApplicable" 的方法来确定给定的 Person 是否可以使用此检查器。或者,在注入时,您可以将 PasswordChecker 映射到正确的人(使用 stream.collect(Collectors.toMap(...)) 方法)。这样你就只需要做一个散列图查找来获得正确的实现。
在我的模块中,我为密码检查程序定义了一个多重绑定。我将我的绑定添加到它。
剩下的大家可以看看
调用我的代码将打印:
User Business Checker
User Client Checker
我希望这就是您要找的 :) 让我知道!
阿图尔
假设我有一个 class 可以根据一组规则验证密码。如何准确验证此密码取决于调用服务器的人。每个不同类型的人对某些规则都有不同的实现。假设 LengthRule 在严格验证中要求长度为 12,在正常验证中要求长度为 8,在宽松验证中要求长度为 5。
根据传递的参数更改所有规则绑定的最佳方法是什么,例如分组布线并动态切换它们?
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 的答案。一般:您可以将多个实现绑定到给定接口,然后注入一组实现。
我要做的是绑定我所有的密码检查器,注入它们,然后使用该组来确定要做什么。
这是完整的 运行 示例:
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;
}
}
测试 class 就是你的例子。它需要一个密码和一个 Person 枚举。
每个 PasswordChecker 实现一个名为 "isApplicable" 的方法来确定给定的 Person 是否可以使用此检查器。或者,在注入时,您可以将 PasswordChecker 映射到正确的人(使用 stream.collect(Collectors.toMap(...)) 方法)。这样你就只需要做一个散列图查找来获得正确的实现。
在我的模块中,我为密码检查程序定义了一个多重绑定。我将我的绑定添加到它。
剩下的大家可以看看
调用我的代码将打印:
User Business Checker
User Client Checker
我希望这就是您要找的 :) 让我知道!
阿图尔