如何在Jersey应用中实现HK2 Factory单例?技术问询
在Jersey HK2中实现单例Factory
嘿,我来帮你把Jersey里HK2的单例Factory实现给理清楚!首先先纠正你代码里的一个小失误——你的provide()方法返回类型应该是SomeObject(毕竟Factory的泛型是SomeObject),不是MyFactory,我先给你补全正确的基础代码,再一步步讲单例的两种常见实现场景:
import org.glassfish.hk2.api.Factory; import org.glassfish.hk2.api.CloseableService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; public class MyFactory implements Factory<SomeObject> { private static final Logger logger = LoggerFactory.getLogger(MyFactory.class); private final CloseableService closeService; // 用于存储单例对象的实例(如果需要让创建的对象是单例) private SomeObject singletonInstance; @Inject public MyFactory(CloseableService closeService) { this.closeService = closeService; } @Override public SomeObject provide() { logger.debug("Providing SomeObject instance"); // 这里根据需求返回实例,后面会讲单例逻辑 return getOrCreateSingletonInstance(); } @Override public void dispose(SomeObject instance) { // 注册对象的销毁逻辑,应用关闭时CloseableService会自动调用 closeService.add(instance::close); } // 线程安全的单例创建逻辑(双重检查锁) private SomeObject getOrCreateSingletonInstance() { if (singletonInstance == null) { synchronized (this) { if (singletonInstance == null) { singletonInstance = new SomeObject(); // 这里可以添加SomeObject的初始化逻辑 } } } return singletonInstance; } }
场景1:让Factory本身成为单例
HK2默认会把Factory实例按每请求的作用域创建(也就是每次需要SomeObject时,都会新建一个MyFactory实例)。如果要让整个应用生命周期里只有一个MyFactory实例,只需要给MyFactory类加上@Singleton注解:
import org.jvnet.hk2.annotations.Singleton; @Singleton public class MyFactory implements Factory<SomeObject> { // 其余代码和上面一致 }
然后在你的Jersey配置类(继承ResourceConfig)里注册Factory时,确保作用域匹配:
import org.glassfish.jersey.server.ResourceConfig; import org.jvnet.hk2.annotations.Singleton; public class MyApplication extends ResourceConfig { public MyApplication() { // 绑定Factory到SomeObject,同时指定作用域为Singleton bindFactory(MyFactory.class).to(SomeObject.class).in(Singleton.class); // 如果你已经给MyFactory加了@Singleton注解,也可以简化成: // bindFactory(MyFactory.class).to(SomeObject.class); } }
场景2:让Factory创建的SomeObject成为单例
如果不需要Factory本身是单例,但希望每次调用provide()都返回同一个SomeObject实例,有两种方式:
方式A:手动实现单例逻辑
就是上面代码里的getOrCreateSingletonInstance()方法,用双重检查锁保证线程安全,手动控制只创建一次SomeObject。
方式B:利用HK2的作用域管理(更推荐)
直接在注册Factory时,指定SomeObject的作用域为Singleton,HK2会自动帮你处理单例逻辑——它只会调用一次provide(),后续所有依赖注入SomeObject的地方都会拿到同一个实例,而且应用关闭时会自动调用dispose():
public class MyApplication extends ResourceConfig { public MyApplication() { // 绑定Factory,同时指定SomeObject的作用域为Singleton bindFactory(MyFactory.class).to(SomeObject.class).in(Singleton.class); } }
这种方式不需要你自己写单例逻辑,HK2会帮你处理线程安全和生命周期管理,更符合HK2的设计理念。
关键注意事项
- 如果
SomeObject需要依赖其他HK2管理的对象,不要在Factory里手动new,最好通过@Inject把依赖注入到MyFactory,再传递给SomeObject的构造函数。 - 如果你手动实现单例,一定要注意线程安全,避免多请求并发时创建多个实例。
- 一定要在
dispose()方法里把SomeObject注册到CloseableService,这样应用关闭时才能正确释放资源。
内容的提问来源于stack exchange,提问作者rawat
相关产品推荐
相关产品推荐

