gpt4 book ai didi

java - 使用 Google Guice 根据上下文绑定(bind)两个不同的接口(interface)实现

转载 作者:行者123 更新时间:2023-12-01 14:50:01 24 4
gpt4 key购买 nike

假设我有一个名为 IValidator 的接口(interface)看起来像下面这样:

public interface IValidator {
/**
* Returns true if the specified strings are valid.
*/
public boolean validate(List<String> someStrings);
}

现在假设我有 IValidator 的两个实现:

public class StrictValidator implements IValidator {
public boolean validate(List<String> someStrings) {
//some strict validation code
return false;
}
}

public class LaissezFaireValidator implements IValidator {
public boolean validate(List<String> someStrings) {
//some easy-going validation code
return true;
}
}

现在让我们添加一个使用 IValidator 的注入(inject)实例的 servlet :

@Service
@At("/rest")
public class MyServlet extends AbstractServlet {

private final IValidator validator;

@Inject
public MyServlet(final IValidator validator) {
this.validator = validator;
}

@Post
@At("/validate")
@LaissezFaire
public Reply<?> validate(Request request) {
//get the strings to validate out of the request object
List<String> strings = (List<String>) restUtil.parseRequest(request, List.class);

//validate the request
if (!this.validator.validate(strings)) {
return Reply.saying().status(409);
} else {
return Reply.saying().noContent();
}
}
}

当然我们还需要绑定(bind)IValidatorStrictValidator在模块中:

public class ValidatorModule implements Module {
@Override
protected void configure() {
bind(IValiator.class).to(StrictValidator.class);
}
}

但是如果我想有条件地绑定(bind) IValidator 会发生什么至StrictValidator在一种情况下,而是将其绑定(bind)到 LaissezFaireValidator在其他情况下?

你注意到@LaissezFaire了吗? MyServlet.validate 上的注释多于?这是一个如下所示的拦截器:

@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LaissezFaire { }

public class LaissezFaireInterceptor implements MethodInterceptor {
private boolean debug;
private IValidator validator;

@Inject
public void setDebug(@Named("debug.enabled") boolean debugEnabled) {
this.debug = debugEnabled;
}

@Inject
public void setValidator(final IValidator validator) {
this.validator = validator;
}

@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
if (debug) {
if (!this.validator.validate(strings)) {
return Reply.saying().status(409);
} else {
return Reply.saying().noContent();
}
} else {
return invocation.proceed();
}
}
}

我们再次需要一些绑定(bind)来设置拦截器:

public class InterceptorModule implements Module {
@Override
protected void configure() {
final MethodInterceptor lfInterceptor = new LaissezFaireInterceptor();
requestInjection(lfInterceptor);
bindInterceptor(Matchers.subclassesOf(AbstractServlet.class), Matchers.AnnotatedWith(LaissezFaire.class), lfInterceptor);
}
}

根据ValidatorModuleLaissezFaireInterceptor类将获得 StrictValidator 的实例当InterceptorModule来电 requestInjection(lfInterceptor); .

相反,我想要 MyServlet获取 StrictValidator 的实例和LaissezFaireInterceptor获取 LaissezFaireValidator 的实例.

根据the Google Guice docs ,当我请求注入(inject)时,我可以使用命名注释。 MyServlet的构造函数将被修改为如下所示:

    @Inject
public MyServlet(@Named("strict") final IValidator validator) {
this.validator = validator;
}

setValidator方法LaissezFaireInterceptor将被修改为如下所示:

    @Inject
public void setValidator(@Named("laissezfaire") final IValidator validator) {
this.validator = validator;
}

最后是ValidatorModule将被修改为如下所示:

public class ValidatorModule implements Module {
@Override
protected void configure() {
bind(IValiator.class).annotatedWith(Names.named("strict")).to(StrictValidator.class);
bind(IValidator.class).annotatedWith(Names.named("laissezfaire")).to(LaissezFaireValidator.class);
}
}

这一切都很好,只是文档特别指出要避免这种方法,因为编译器无法检查字符串名称。另外,这意味着我必须添加一个@Named对代码中请求 IValidator 的每个位置进行注释通过注入(inject),否则绑定(bind)失败。

我真的希望Provider Bindings可以为我解决这个问题,但他们似乎对进行绑定(bind)的上下文一无所知。由于他们不知道请求绑定(bind)的类的类型,因此我无法选择IValidator的类型。从 get() 返回方法。

有没有更好的方法来解决这个问题?

最佳答案

同时Condit提供了一些很好的建议,我们选择用更直接的解决方案来解决这个问题。

如上所述,我们创建了 IValidator 接口(interface),以及 StrictValidatorLaissezFaireValidator 类。在默认情况下,我们使用 ValidatorModuleIValidator 绑定(bind)到 StrictValidator。提醒一下,它看起来像这样:

public class ValidatorModule implements Module {
@Override
protected void configure() {
//in the default case, inject an instance of StrictValidator
bind(IValiator.class).to(StrictValidator.class);
}
}

在绝大多数情况下,StrictValidator 是必需的实现,因为 LaissezFaireInterceptor 是用于测试的作弊程序。

无论我们想要一个 StrictValidator(就像我们在 MyServlet 中所做的那样),我们都会注入(inject)一个 IValidator 实例:

public class MyServlet extends AbstractServlet {

private final IValidator validator;

@Inject
public MyServlet(final IValidator validator) {
this.validator = validator;
}

//... there's more code here (look above) ...
}

无论我们想要 LaissezFaireValidator 的实例,我们都要求注入(inject)它的具体实现来代替 IValidator:

public class LaissezFaireInterceptor implements MethodInterceptor {

private final IValidator validator;

//... a bunch of other code goes here (see above) ...

@Inject
public void setValidator(final LaissezFaireValidator validator) {
this.validator = validator;
}

//... and a bunch more code goes here (again, see above) ...
}

通过这种方式,我们能够根据注入(inject)的上下文有条件地注入(inject)所需的实现,而无需引入任何额外的注释或工厂。

当然,它并不像它可能的那样Guicy,但它确实有效。

关于java - 使用 Google Guice 根据上下文绑定(bind)两个不同的接口(interface)实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14983612/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com