Dependency injection 在Jersey 2中使用内置Jersey依赖项注入创建简单的singleton类时遇到问题
我很难用Jersey 2(2.7)和Jersey的内置HK2依赖注入实现一个非常基本的singleton类。我在Tomcat上运行这个 我的目标是创建一个支持类的单例实例,该实例将由各种web服务方法使用。在构造函数注入、方法注入和注释类成员之间,我没有强烈的偏好(如下所述) 这是我的未来单身班:Dependency injection 在Jersey 2中使用内置Jersey依赖项注入创建简单的singleton类时遇到问题,dependency-injection,singleton,jax-rs,jersey-2.0,hk2,Dependency Injection,Singleton,Jax Rs,Jersey 2.0,Hk2,我很难用Jersey 2(2.7)和Jersey的内置HK2依赖注入实现一个非常基本的singleton类。我在Tomcat上运行这个 我的目标是创建一个支持类的单例实例,该实例将由各种web服务方法使用。在构造函数注入、方法注入和注释类成员之间,我没有强烈的偏好(如下所述) 这是我的未来单身班: package-singletest; 导入javax.inject.Singleton; @独生子女 公务舱JustOne{ 私有整数secretNumber=0; 公共无效hitMe(整数输入){
package-singletest;
导入javax.inject.Singleton;
@独生子女
公务舱JustOne{
私有整数secretNumber=0;
公共无效hitMe(整数输入){
secretNumber+=输入;
}
@凌驾
公共字符串toString(){
返回String.format(“{\“secretNumber\”:%s}”,secretNumber);
}
}
这是我的应用程序类:
package-singletest;
导入javax.ws.rs.ApplicationPath;
导入javax.ws.rs.core.Application;
导入java.util.HashSet;
导入java.util.Set;
@应用程序路径(“/*”)
公共类MainApplication扩展了应用程序{
@凌驾
public Set>classes=new HashSet();
添加(TestResource.class);
返回类;
}
@凌驾
公共集getSingleton(){
Set singleton=newhashset();
添加(新的JustOneProvider());
返回单身人士;
}
}
以下是我的提供程序/上下文解析器类:
package-singletest;
导入javax.ws.rs.ext.ContextResolver;
导入javax.ws.rs.ext.Provider;
@提供者
公共类JustOneProvider实现ContextResolver{
私有静态JustOne JustOne=新JustOne();
@凌驾
public JustOne getContext(类类型){
只返回一个;
}
}
web.xml:
singletest.main应用程序
org.glassfish.jersey.servlet.ServletContainer
javax.ws.rs.Application
singletest.main应用程序
jersey.config.servlet.filter.forwardOn404
真的
singletest.main应用程序
/*
我打算在其中注入JustOne类的singleton实例的资源:
package-singletest;
导入javax.inject.inject;
导入javax.ws.rs.*;
导入javax.ws.rs.core.MediaType;
导入javax.ws.rs.core.Response;
@路径(“/test”)
公共类测试资源{
@注入
私人一对一;
@得到
@使用(MediaType.TEXT\u PLAIN)
@产生(MediaType.APPLICATION_JSON)
@路径(“/func1/{input}”)
公共响应func1(@PathParam(“input”)int-input){
justOne.hitMe(输入);
String responseData=justOne.toString();
返回Response.ok(responseData.build();
}
}
在泽西岛部署/初始化war时发出此警告:
Apr 28, 2014 11:48:25 AM org.glassfish.jersey.server.ApplicationHandler initialize
INFO: Initiating Jersey application, version Jersey: 2.7 ${buildNumber}...
Apr 28, 2014 11:48:25 AM org.glassfish.jersey.internal.inject.Providers checkProviderRuntime
WARNING: A provider java.lang.Class registered in SERVER runtime does not implement any provider interfaces applicable in the SERVER runtime. Due to constraint configuration problems the provider java.lang.Class will be ignored.
以及调用此web服务时出现的错误:
type Exception report
message A MultiException has 3 exceptions. They are:
description The server encountered an internal error that prevented it from fulfilling this request.
exception
javax.servlet.ServletException: A MultiException has 3 exceptions. They are:
1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at Injectee(requiredType=JustOne,parent=TestResource,qualifiers={}),position=-1,optional=false,self=false,unqualified=null,58952407)
2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of singletest.TestResource errors were found
3. java.lang.IllegalStateException: Unable to perform operation: resolve on singletest.TestResource
org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:333)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:372)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:218)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
所以,我明白了:hk2没有获得足够的信息来创建/绑定JustOne实例和/或查找/使用我的JustOneProvider。我肯定我错过了一些基本的东西。任何指导都将不胜感激。好的,在花了大量时间在这上面之后,我让它工作起来了 我使用了HK2AbstractBinder和JAX-RS特性(javax.ws.RS.core.Feature) 事实证明,不需要提供程序/上下文解析器 应用程序:
导入javax.ws.rs.ApplicationPath;
导入javax.ws.rs.core.Application;
导入java.util.HashSet;
导入java.util.Set;
@应用程序路径(“/*”)
公共类MainApplication扩展了应用程序{
@凌驾
public Set>classes=new HashSet();
添加(TestResource.class);
添加(JustOneFeature.class);
返回类;
}
}
要成为单身阶级:
公共类JustOne{
私有整数secretNumber=0;
public int getSecretNumber(){
返回secretNumber;
}
公共机密编号(){
secretNumber+=1;
}
}
活页夹:
import org.glassfish.hk2.utilities.binding.AbstractBinder;
公共类JustOneBinder扩展了AbstractBinder{
@凌驾
受保护的void configure(){
绑定(新的JustOne()).to(JustOne.class);
}
}
特色:
导入javax.ws.rs.core.Feature;
导入javax.ws.rs.core.FeatureContext;
公共类JustOneFeature实现该功能{
@凌驾
公共布尔配置(最终功能上下文){
register(新的JustOneBinder());
返回true;
}
}
注入单例的资源:
import javax.inject.inject;
导入javax.ws.rs.*;
导入javax.ws.rs.core.MediaType;
导入javax.ws.rs.core.Response;
@路径(“/test”)
公共类测试资源{
@注入
私人一对一;
@得到
@使用(MediaType.TEXT\u PLAIN)
@产生(MediaType.APPLICATION_JSON)
@路径(“/func1/{input}”)
公共响应func1(@PathParam(“input”)int-input){
justOne.bumpSecretNumber();
String responseData=String.format(“{\”结果\“:%s}”,输入+justOne.getSecretNumber());
返回Response.ok(responseData.build();
}
}
这是最重要的部分。如果没有“in(Singleton.class)”,将创建JustOne的多个实例。哦,不,那不是真的。在此上下文中,您不需要“In(Singleton.class)”。我使用了多个活页夹/功能对,它们都使用“bind(new JustOne()).to(JustOne.class)”(用于除我在这里示例中使用的JustOne以外的各种类)。这些对中没有一个使用“in(Singleton.class)”。尽管如此,如果我在以这种方式创建的单例的构造函数中设置断点,它只会被调用一次,即使注入了这些单例类之一的web服务被调用了几十次。如果从未指定生命周期,HK2如何知道注册为singleton。是单身吗
bind(JustOne.class).to(JustOne.class).in(Singleton.class);