Jersey Singleton 多次实例化

Jersey Singleton instantiated multiple time

我必须制作一个非常小的 REST 应用程序,即使我习惯了 Spring,Jersey 似乎比 Spring 更轻(也许我错了?)。

我在 Tomcat 8.0.39.

上使用 Jersey 2.25

我有一个 DAO class 当前正在访问一个文本文件(将升级到 jdbc 连接)。那些 read/write 操作必须同步,因此我希望我的 DAO 实例是一个单例。

@Singleton
public class ModelDao extends IModelDao
    public ModelDao() {
        System.out.println("init ModelDao");
    }

    @Override
    public MyModel read(int id){...}
}

这个单例被注入到一个服务中:

@Path("/Model/")
public class ModelService {

    @Inject
    private IModelDao modelDao;

    @Path("{id}")
    @GET
    @Produces("application/json")
    public MyModel getModel(@PathParam("id") Integer id) {
        return modelDao.read(id);
    }
}

通过活页夹

public class DaoBinder extends AbstractBinder {
    @Override
    protected void configure() {
        bind(ModelDao.class).to(IModelDao.class);
    }
}

ResourceConfig 中,我注册了活页夹和我的包。 当我使用我的服务时,我得到了正确的数据,但每个请求都会调用 ModelDao 构造函数。所以 read/write 操作不同步。

我理解 class 注释 @Singleton 应该在我的应用程序中只实例化一次。 我是不是理解错了?

将 class 设置为单例后,是否在应用程序中注册它?

像这样:

public class App extends ResourceConfig {
    public App () {
        register(ModelDao.class);
    }
}

通过AbstractBinder 与Jersey 绑定服务,不支持@Singleton 注释。您需要使用 bind().to().in(Scope) 语法,其中 Scope 例如Singleton.classRequestScoped.class。默认范围是 PerLookup,这是导致您当前遇到的行为的原因。

此外,您可以使用 bind(Instance).to(Class) 而不是 bind(Class).to(Class),这将自动使其成为单例,而无需 g 指定范围。