我已经能够根据过滤器注入我的球衣资源如何将对象注入球衣请求上下文中?。这使我能够成功注入方法参数:
@GET
public Response getTest(@Context MyObject myObject) { // this works
但是,对于 setter/field/constructor 注入,将调用 HK2 Factorybeforejersey 过滤器,这意味着 Provide() 方法返回 null:
@Override
public MyObject provide() {
// returns null because the filter has not yet run,
// and the property has not yet been set
return (MyObject)context.getProperty("myObject");
}
有没有办法定义 HK2 Factory 何时运行以便调用它after过滤器运行?如果不是,那么解决方法是将 MyObject 定义为接口,并定义一个在其构造函数中采用 ContainerRequestContext 的附加实现;任何实际使用该实例的尝试都会延迟地委托给在 ContainerRequestContext 的属性上设置的实现(大概您在过滤器运行之前不会实际使用该实例 - 此时将设置该属性)。
但我想了解是否可以延迟 HK2 Factory 的运行点,以便它在过滤器之后运行(在方法参数注入的情况下,它已经在过滤器之后运行)。如果不可能,那么我想了解是否有根本原因。
奇怪的是它只对我有用@PreMatching
在过滤器上(这限制了对您可能需要或不需要的某些内容的访问)。不太确定引擎盖下发生了什么,这会导致它在没有它的情况下无法工作:-(。下面是使用的完整测试泽西岛测试框架.
import java.io.IOException;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import javax.ws.rs.ext.Provider;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.process.internal.RequestScoped;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.internal.inject.AbstractContainerRequestValueFactory;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Assert;
import org.junit.Test;
public class FilterInjectionTest extends JerseyTest {
private static final String MESSAGE = "Inject OK";
private static final String OBJ_PROP = "myObject";
public static class MyObject {
private final String value;
public MyObject(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
@PreMatching
@Provider
public static class MyObjectFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext context) throws IOException {
MyObject obj = new MyObject(MESSAGE);
context.setProperty(OBJ_PROP, obj);
}
}
public static class MyObjectFactory
extends AbstractContainerRequestValueFactory<MyObject> {
@Override
@RequestScoped
public MyObject provide() {
return (MyObject) getContainerRequest().getProperty(OBJ_PROP);
}
@Override
public void dispose(MyObject t) {
}
}
@Path("method-param")
public static class MethodParamResource {
@GET
public String getResponse(@Context MyObject myObject) {
return myObject.getValue();
}
}
@Path("constructor")
public static class ConstructorResource {
private final MyObject myObject;
@Inject
public ConstructorResource(@Context MyObject myObject) {
this.myObject = myObject;
}
@GET
public String getResponse() {
return myObject.getValue();
}
}
@Path("field")
public static class FieldResource {
@Inject
private MyObject myObject;
@GET
public String getResponse() {
return myObject.getValue();
}
}
@Override
public Application configure() {
ResourceConfig config = new ResourceConfig();
config.register(MethodParamResource.class);
config.register(MyObjectFilter.class);
config.register(ConstructorResource.class);
config.register(FieldResource.class);
config.register(new AbstractBinder() {
@Override
protected void configure() {
bindFactory(MyObjectFactory.class)
.to(MyObject.class).in(Singleton.class);
}
});
return config;
}
@Test
public void methoParamInjectionOk() {
String response = target("method-param").request().get(String.class);
Assert.assertEquals(MESSAGE, response);
System.out.println(response);
}
@Test
public void costructorInjectionOk() {
String response = target("constructor").request().get(String.class);
Assert.assertEquals(MESSAGE, response);
System.out.println(response);
}
@Test
public void fieldInjectionOk() {
String response = target("field").request().get(String.class);
Assert.assertEquals(MESSAGE, response);
System.out.println(response);
}
}
UPDATE
解决方案,无需使其成为@PreMatching
过滤器,是注入javax.inject.Provider。这将允许您延迟检索对象。我想构造函数和字段注入会发生什么,在匹配资源类之后,它立即创建并注入。因为过滤器还没有被调用,所以工厂没有对象。它适用于方法注入,因为它就像任何其他方法调用一样。当调用该方法时,该对象被传递给它。下面是示例javax.inject.Provider
@Path("constructor")
public static class ConstructorResource {
private final javax.inject.Provider<MyObject> myObjectProvider;
@Inject
public ConstructorResource(javax.inject.Provider<MyObject> myObjectProvider) {
this.myObjectProvider = myObjectProvider;
}
@GET
public String getResponse() {
return myObjectProvider.get().getValue();
}
}
@Path("field")
public static class FieldResource {
@Inject
private javax.inject.Provider<MyObject> myObjectProvider;;
@GET
public String getResponse() {
return myObjectProvider.get().getValue();
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)