Jersey 2单例依赖注入创建多个实例

时间:2015-08-24 21:49:10

标签: java dependency-injection jersey singleton jersey-2.0

这里我有一个单身人士,我想注入我的应用程序

def changeWords(sentence):
    for char in sentence:
        if char == 'a':
            printSameLine('x')
        elif char == 'bd':
            printSameLine('y')
        else:
            printSameLine(char)

def goWordChange():
    print('')
    print('paste text to change')
    print('')
    text = input()
    print('')
    changeWords(text)
    print('')
    return goWordChange()

goWordChange()

以下是我注册的方式:

@Singleton
@Path("singleton-bean")
public class MyContext {

    private MyContext() {
        instances++;
    }

    private static MyContext instance;

    public static MyContext getInstance(){
        if (instance == null)
            instance = new MyContext();
        return instance;
    }

    public static int instances = 0;

}

最后,我在请求中打印单身人士:

@ApplicationPath("webresources")
public class ApplicationConfig extends Application {

    @Override
    public Set<Object> getSingletons() {
        final Set<Object> singletons = new HashSet<>();
        singletons.add(MyContext.getInstance());
        return singletons;
    }

    //.....

它返回两个实例。我知道Jersey使用反射来访问私有构造函数并创建另一个实例。为什么会发生这种情况?如何防止这种情况发生?

1 个答案:

答案 0 :(得分:4)

getSingletons与注射无关。它意味着注册单个JAX-RS组件(即资源类和提供者),这些组件实际上并不需要是经典的&#34;单身。它们只能是普通类的实例。

要使用Jersey 2.x处理任意组件/服务的注入,请参阅Custom Injection and Lifecycle Management

一般模式是创建Factory<T>实现,其中T是可注入类型。然后工厂需要在Jersey运行时注册。一种方法是通过AbstractBinder。例如

public class MyContextProvider implements Factory<MyContext> {

    @Override
    public MyContext provide() {
        return new MyContext();
    }

    @Override
    public void dispose(Bar bar) {}
}

然后将它绑定在ResourceConfig的子类(Application的子类)中。

@ApplicationPath("/webresources")
public class AppConfig extends ResourceConfig {

    public AppConfig() {

        packages("com.stackoverflow.jersey");

        register(new AbstractBinder(){
            @Override
            protected void configure() {
                bindFactory(MyContextProvider.class)
                        .to(MyContext.class)
                        .in(Singleton.class);
            }
        });
    }
}

packages方法允许扫描资源类(使用@Path注释的类)和提供程序(使用@Provider注释的类)的包和子包,因此您不需要&# 39;需要明确注册它们。

您还需要确保拥有所有必需的编译时依赖项。如果您使用的是Maven,请使用

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet</artifactId>
    <version>2.19</version>
    <scope>provided</scope>
</dependency> 

provided范围适用于您使用Glassfish的情况,因为Glassfish alredy有罐子。你不想复制不同版本的罐子。如果您只是在像Tomcat这样的servlet容器中,则可以删除<scope>。如果您不使用Maven,则需要从Jersey JAX-RS 2.0 RI bundle手动添加jar。同样,如果你在Glassfish中,你需要让jar只是编译时的罐子。你不想把它们包括在战争的构建中。