Jaa*_*ers 3 java spring dependency-injection jersey hk2
我正在尝试创建一个注入解析器。我有一个数据类:
public class MyData {
...
}
Run Code Online (Sandbox Code Playgroud)
我有以下注释:
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyDataInject {
}
Run Code Online (Sandbox Code Playgroud)
我的注入解析器如下所示:
public class MyDataInjectionResolver extends ParamInjectionResolver<MyDataInject> {
public MyDataInjectionResolver () {
super(MyDataValueFactoryProvider.class);
}
@Singleton
public static class MyDataValueFactoryProvider extends AbstractValueFactoryProvider {
@Inject
public MyDataValueFactoryProvider(MultivaluedParameterExtractorProvider provider, ServiceLocator locator) {
super(provider, locator, Parameter.Source.UNKNOWN);
}
@Override
protected Factory<?> createValueFactory(Parameter parameter) {
System.out.println(parameter.getRawType());
System.out.println(Arrays.toString(parameter.getAnnotations()));
System.out.println("------------------------------------------------------------------");
System.out.println();
... create factory and return ...
}
}
}
Run Code Online (Sandbox Code Playgroud)
我绑定如下:
bind(MyDataValueFactoryProvider.class).to(ValueFactoryProvider.class).in(Singleton.class);
bind(MyDataInjectionResolver.class).to(new TypeLiteral<InjectionResolver<MyDataInject>>() {}).in(Singleton.class);
Run Code Online (Sandbox Code Playgroud)
为了简洁起见,我省略了实际工厂的实现。一切正常,但我注意到一些我无法解释的行为。我正在使用以下 JAX-RS 资源进行测试:
@Path("test")
public class Test {
@GET
public Response test(@MyDataInject @Valid MyData data) {
return Response.status(Response.Status.OK).entity("Hello world!").build();
}
}
Run Code Online (Sandbox Code Playgroud)
MyDataValueFactoryProvider.createValueFactory在启动期间被调用两次。这是为什么?这听起来像是一些错误。好处是,当客户端发出请求时,工厂仅被访问一次。@MyDataInject资源中的注释,如下 (*) 所示,MyDataValueFactoryProvider.createValueFactory仍然会被调用。这是为什么?这很奇怪,因为它应该仅限于@MyDataInject? (更新)当参数不属于类时甚至会调用它MyData,请参见下面的第二个变体。(*) 没有@MyDataInject注释的资源:
@Path("test")
public class Test {
@GET
public Response test(/*@MyDataInject*/ @Valid MyData data) {
return Response.status(Response.Status.OK).entity("Hello world!").build();
}
}
Run Code Online (Sandbox Code Playgroud)
另一种变体:
@Path("test")
public class Test {
@GET
public Response test(@Valid SomeOtherClass data) {
return Response.status(Response.Status.OK).entity("Hello world!").build();
}
}
Run Code Online (Sandbox Code Playgroud)
启动时,Jersey 会构建所有资源的内部模型。Jersey 使用此模型来处理请求。该模型的一部分由所有资源方法及其所有参数组成。更进一步,泽西岛还将验证该模型,以确保它是一个有效的模型。模型中的某些无效内容可能会导致 Jersey 无法在运行时处理该模型。所以这个验证是为了保护我们。
也就是说,验证过程的一部分是验证方法参数。有一些规则控制着我们可以将什么作为参数。例如,参数必须满足javadoc@QueryParam中提到的要求之一:
valueOf或 的静态方法fromString,它接受单个字符串参数(例如,参见Integer.valueOf(String))ParamConverterProvider拥有JAX-RS 扩展 SPI的注册实现,该实现返回ParamConverter能够进行类型“从字符串”转换的实例。List<T>、Set<T>或SortedSet<T>,其中T满足上述 2、3 或 4。生成的集合是只读的。您可以尝试以下方法。添加@QueryParam使用以下任意类
public class Dummy {
public String value;
}
@GET
public Response get(@QueryParam("dummy") Dummy dummy) {}
Run Code Online (Sandbox Code Playgroud)
请注意,该类Dummy不满足上面列出的任何要求。当您运行应用程序时,您应该在启动时遇到异常,从而导致应用程序失败。例外情况会是这样的
ModelValidationException: No injection source for parameter ...
Run Code Online (Sandbox Code Playgroud)
这意味着模型验证失败,因为 Jersey 不知道如何Dummy从查询参数创建实例,因为它不遵循允许的规则。
好的。那么这一切与你的问题有什么关系呢?好吧,所有参数注入都需要 aValueFactoryProvider能够为其提供值。如果没有,则无法在运行时创建该参数。ValueFactoryProvider因此 Jersey 通过检查返回 a 的a 是否存在来验证参数Factory。Jersey 在运行时调用获取 的方法Factory就是您提到的方法:createValueFactory。
现在请记住,当我们实现 时createValueFactory,我们可以返回 aFactory也可以返回 null。我们应该如何实现它,是检查Parameter参数以查看我们是否可以处理该参数。例如
protected Factory<?> createValueFactory(Parameter parameter) {
if (parameter.getRawType() == Dummy.class
&& parameter.isAnnotationPresent(MyAnnoation.class)) {
return new MyFactory();
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
所以在这里我们告诉 Jersey 它ValueFactoryProvider可以处理什么。在这种情况下,我们可以处理类型的参数Dummy,并且如果参数带有注释@MyAnnotation。
那么在启动验证期间会发生什么,对于每个参数,Jersey 都会遍历每个ValueFactoryProvider注册的参数,看看是否有一个可以处理该参数。它知道的唯一方法是调用该createValueFactory方法。如果有一个返回a Factory,那么就成功了。如果所有的ValueFactoryProviders都被遍历并且都返回null,那么模型无效,我们将得到模型验证异常。需要注意的是,有一堆内部的ValueFactoryProvider参数,带有@QueryParam、@PathParam等注释。
| 归档时间: |
|
| 查看次数: |
3944 次 |
| 最近记录: |