我已经使用 Spring Rest 完成了项目。现在我们有一个小型的休息项目并计划使用 Jersey JAX-RS。我对此并不陌生,并引用了 SO 和其他博客以成功实现具有依赖项注入(inject)的 Rest api。
有如下代码。
AppConfig.java
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationPath("/")
public class AppConfig extends Application {
@Override
public Set<Class<?>> getClasses() {
System.out.println("AppConfig");
final Set<Class<?>> s = new HashSet<Class<?>>();
s.add(Controller.class);
s.add(AppFeature.class);
return s;
}
}
AppBinder.java
import org.glassfish.hk2.utilities.binding.AbstractBinder;
public class AppBinder extends AbstractBinder {
@Override
protected void configure() {
System.out.println("AppBinder");
bind(ReflectionService.class).to(ReflectionService.class);
}
}
AppFeature.java
import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;
public class AppFeature implements Feature {
@Override
public boolean configure(FeatureContext context) {
System.out.println("AppFeature");
context.register(new AppBinder());
return true;
}
}
Controller.java
@Path("/")
public class Controller {
@Inject
Service service;
public Controller(){
System.out.println("Controller created");
}
// other methods
}
服务.java
@Singleton
public class Service
public Service(){
System.out.println("Service instance created");
}
// other methods
}
我假设 Controller 和服务的每个实例都是在 Tomcat 8 服务器启动时创建的,并且依赖注入(inject)已完成。但是在启动期间,在控制台上得到了这个
INFO: Registering the Jersey servlet application, named com.sample.auto2.AppConfig, at the servlet mapping /*, with the Application class of the same name.
AppConfig
AppConfig
Nov 15, 2016 12:22:20 PM org.glassfish.jersey.server.ApplicationHandler initialize INFO: Initiating Jersey application, version Jersey: 2.6 2014-02-18 21:52:53...
AppFeature
AppBinder
Nov 15, 2016 12:22:21 PM org.apache.catalina.startup.HostConfig deployDirectory
每次,我们发送一个请求,在控制台中得到关注
Service instance created
Controller created
我的问题
- 服务,每当我们发送一个 http请求;它是在每个请求中创建实例还是只是 调用构造函数?
- 为什么 AppConfig 中的 System.out 被调用两次?
- 有没有更好的方法来设置我的小项目,它没有任何数据库访问权限,只有三个 post 端点?
编辑:
根据@Harikrishnan 提供的链接,为Controller
类添加了@Singleton
。现在构造函数只调用一次(在第一次请求时 - 为什么不在服务器启动期间!!)。
但为什么服务类构造函数在每个请求上调用(在将 @Singleton 添加到 Controller 之前),即使它是单例?其他问题也依然存在。
编辑 2:
谢谢@peeskillet。所以这些是我的结果。
这只在第一次请求时调用构造函数一次
bind(ReflectionService.class).to(ReflectionService.class).in(Singleton.class); bind(Controller.class).to(Controller.class).in(Singleton.class);
http请求报错
bind(ReflectionService.class).to(ReflectionService.class).in(Immediate.class); java.lang.IllegalStateException: Could not find an active context for org.glassfish.hk2.api.Immediate
不过没关系,因为
这会在服务器启动时调用构造函数,并且只调用一次
bind(new ReflectionService()).to(ReflectionService.class); bind(new Controller()).to(Controller.class);
由此,注入(inject)在启动时完成,但在 http 请求时出现 404 错误。 (以为Controller是在AppBinder中配置的,那为什么在AppConfig中)
@ApplicationPath("/") public class AppConfig extends ResourceConfig { public AppConfig() { register(new AppBinder()); } }
这让它运行起来,正如您所说的!
@ApplicationPath("/") public class AppConfig extends ResourceConfig { public AppConfig() { register(new AppBinder()); register(Controller.class); } }
最后这些就是我所需要的
public class AppBinder extends AbstractBinder {
@Override
protected void configure() {
bind(new ReflectionService()).to(ReflectionService.class);
bind(new Controller()).to(Controller.class);
}
}
@ApplicationPath("/")
public class AppConfig extends ResourceConfig {
public AppConfig() {
register(new AppBinder());
register(Controller.class);
}
}
最佳答案
Service,Controller constructors is being called whenever we send an http request; does it create instances in each request or just calling constructor?
不幸的是,@Singleton
在使用 AbstractBinder
进行绑定(bind)时没有任何效果。我们需要明确的说应该是单例
bind(ReflectionService.class).to(ReflectionService.class).in(Singleton.class);
默认行为是“每次查找”作用域,这意味着每次请求服务时都会创建一个新实例
(at the very first request - Why not during server startup!!)
这就是它的工作原理。还有一个 ImmediateScope
,这将导致它在启动时创建
bind(ReflectionService.class).to(ReflectionService.class).in(ImmediateScope.class)
或者你可以只使用一个实例而不是类,它会自动成为一个单例
bind(new ReflectionService()).to(ReflectionService.class)
Service,Controller constructors is being called whenever we send an http request; does it create instances in each request or just calling constructor?
这是默认行为。每个请求的资源类的新实例。如前所述,如果您只想要一次实例,则将其标记为 @Singleton
Why System.out in AppConfig is called twice?
不确定,可能只是 Jersey 内部 Bootstrap 需要的
Is there a better way for setting up my small project, which does not have any db access and only three post endpoints?
您的设置很好,但是如果您使用的是 Jersey,那么您应该使用 ResourceConfig
(Application
的扩展)类而不是 Application
@ApplicationPath("/")
public class AppConfig extends ResourceConfig {
public AppConfig() {
register(new AppBinder());
register(Controller.class);
}
}
这样,您就不需要将 AppBinder
包装在 AppFeature
中。 Jersey 已经知道如何处理 AppBinder
关于java - JAX-RS 依赖注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40603988/