依赖注入 – 泽西@Context范围
发布时间:2020-12-13 20:44:19 所属栏目:百科 来源:网络整理
导读:我很难理解泽西的注射机制. JAX-RS规范( http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-520005)规定,可以在Application子类,根资源类和提供程序中通过@Context进行注入. 我现在有一个在启动时实例化的类,并且有一个在每个请求上调用的方法.
我很难理解泽西的注射机制. JAX-RS规范(
http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-520005)规定,可以在Application子类,根资源类和提供程序中通过@Context进行注入.
我现在有一个在启动时实例化的类,并且有一个在每个请求上调用的方法.在方法内部,我需要访问当前的UriInfo对象.问题是,我的代码没有调用此方法.所以我无法直接将UriInfo传递给该方法. 我其实想做这样的事情: public class MyClass implements ThirdPartyInterface { // not possible because class is no Application subclass,root resource class or provider @Context private UriInfo uriInfo; public void methodCallebByThirdPartyCode() { Uri requestUri = uriInfo.getRequestUri(); // do something } } 我试过这个.显然没有成功: public class MyClass implements ThirdPartyInterface { private UriInfo uriInfo; public MyClass(UriInfo uriInfo) { this.uriInfo = uriInfo; } public void methodCallebByThirdPartyCode() { Uri requestUri = uriInfo.getRequestUri(); // do something } } @Provider @Produces(MediaType.WILDCARD) public class MyBodyWriter implements MessageBodyWriter<MyView> { @Context private UriInfo uriInfo; private MyClass myClass; private ThirdPartyClass thirdPartyClass; public MyBodyWriter() { // uriInfo is null at this time :( myClass = new MyClass(uriInfo); thirdPartyClass = new ThirdPartyClass(); thirdPartyClass.register(myClass); } public void writeTo(final MyView view,final Class<?> type,/* and so on */) throws IOException,WebApplicationException { // execute() calls MyClass#methodCallebByThirdPartyCode() thirdPartyClass.execute(); } } 我能想到的唯一解决方法就是这个.我不认为它很干净: public class MyClass implements ThirdPartyInterface { private UriInfo uriInfo; public void setUriInfo(final UriInfo uriInfo) { this.uriInfo = uriInfo; } public void methodCallebByThirdPartyCode() { Uri requestUri = uriInfo.getRequestUri(); // do something } } @Provider @Produces(MediaType.WILDCARD) public class MyBodyWriter implements MessageBodyWriter<MyView> { @Context private UriInfo uriInfo; private MyClass myClass; private ThirdPartyClass thirdPartyClass; public MyBodyWriter() { myClass = new MyClass(); thirdPartyClass = new ThirdPartyClass(); thirdPartyClass.register(myClass); } public void writeTo(final MyView view,WebApplicationException { myClass.setUriInfo(uriInfo); // execute() calls MyClass#methodCallebByThirdPartyCode() thirdPartyClass.execute(); myClass.setUriInfo(null); } } 我希望有更好的解决方案,但也许我完全走错了路. 谢谢!
迟到的回答,但是一个很好的问题…所以我们走吧:
您可以使用org.glassfish.hk2.api.Factory和javax.inject.Provider进行注射.我不知道从哪个版本可用,所以也许你必须升级你的jersery版本.对于以下样品,我使用了汗布2.12. 首先,您必须为MyClass实现并注册/绑定Factory: MyClassFactory: import javax.inject.Inject; import javax.ws.rs.core.UriInfo; import org.glassfish.hk2.api.Factory; // ... public class MyClassFactory implements Factory<MyClass> { private final UriInfo uriInfo; // we will bind MyClassFactory per lookup later,so // the constructor will be called everytime we need the factory // meaning,uriInfo is also per lookup @Inject public MyClassFactory(final UriInfo uriInfo) { this.uriInfo = uriInfo; } @Override public MyClass provide() { return new MyClass(uriInfo) } @Override public void dispose(UriInfo uriInfo) { // ignore } } 通过ResourceConfig注册: import org.glassfish.hk2.api.PerLookup; import org.glassfish.hk2.utilities.binding.AbstractBinder; import org.glassfish.jersey.server.ResourceConfig; // ... public class MyResourceConfig extends ResourceConfig { public MyResourceConfig() { register(new AbstractBinder() { @Override protected void configure() { bindFactory(MyClassFactory.class).to(MyClass.class).in(PerLookup.class); // ... bind additional factories here } }); // ... } } 现在,您可以将每个查询的MyClass注入提供者,资源等. import javax.inject.Inject; import javax.ws.rs.Produces; import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; // ... @Provider @Produces("application/foo-bar") public class MyBodyWriter implements MessageBodyWriter<MyView> { // first approache - don't do it! // will only injected once,cause MyBodyWriter is only instantiated once @Inject private MyClass myClass; // second approache - works fine! private final javax.inject.Provider<MyClass> provider; // MyBodyWriter instantiate once // get an inject provider here @Inject public MyBodyWriter(javax.inject.Provider<MyClass> myClassProvider) { this.provider = myClassProvider; } @Override public boolean isWriteable(Class<?> t,Type g,Annotation[] a,MediaType m) { return t == MyView.class; } @Override public long getSize(MyView t,Class<?> c,MediaType m) { // deprecated by JAX-RS 2.0 and ignored by Jersey runtime return 0; } @Override public void writeTo(MyView v,Type t,MediaType m,MultivaluedMap<String,Object> s,OutputStream o) throws IOException,WebApplicationException { // attention: its not per lookup !!! MyClass myClassDirectInjected = myClass; System.out.println(myClassDirectInjected); // same instance everytime // but this is ;) MyClass myClassFromProvider = provider.get(); System.out.println(myClassFromProvider); // it's a new instance everytime // ... } } 希望这在某种程度上有所帮助. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |