Jersey/HK2 中一个接口的两个实现,首先在另一个中重用

Two implementations of one interface in Jersey/HK2, reuse first in other

我有一个简单实现的接口,比如说

 interface MyService { 
    void doIt();
 } 

 class MyServicePlain implements MyService{

    @Inject
    SomeOtherInterface

    public void doIt () { 
    }
 }

我想制作一个缓存 doIt 的缓存,所以我写了一个包装器 :

 class CachingMyService implements MyService {

       @Inject 
       MyService inner;

       int cacheThingie;

       public int doIt() {
               if (cached) ... {
                   return cacheThingie;
               } 
               else {
                   result = inner.doIt();
                   addToCache(result);
                   return result;
               }
       }
 }

然后,我将这两个实现添加到我的活页夹中:

   public class ApplicationBinder extends AbstractBinder {

        protected void configure() {
        this.bind(MyServicePlain.class).to(MyService.class).in(Singleton.class).ranked(2);
        this.bind(CachingMyService.class).to(MyService.class).in(Singleton.class).ranked(2);
        }
   }

我收到错误抱怨:

org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=MyService,parent=CachingMyService},position=-1,optional=false,self=false,unqualified=null,1102650897)

我尝试像这样使用 Qualitifaction:

 @Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface NonCached {
}


 @NonCached
 class MyServicePlain implements MyService{
 }

并使用它:

  class CachingMyService implements MyService {

       @Inject @NonCached 
       MyService inner;

但这也不管用。

像这样包装缓存服务的正确方法是什么?我怎样才能让hk2选择合适的实现?

当你想要限定不同的类型时,你需要使用qualifiedBy(Annotation)方法。您还需要使用不同的限定符注释来注释每个注入点。

首先你需要注解并有办法获取它们的实例(qualifiedBy 方法需要注解实例)

@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface NonCached {

    class Literal extends AnnotationLiteral<NonCached> implements NonCached {

        public static final NonCached INSTANCE = new Literal();

        private Literal() {
        }
    }
}

@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface Cached {

    class Literal extends AnnotationLiteral<Cached> implements Cached {

        public static final Cached INSTANCE = new Literal();

        private Literal() {
        }
    }
}

然后当你绑定它们时使用 qualifiedBy

this.bind(MyServicePlain.class).to(MyService.class)
    .in(Singleton.class).qualifiedBy(NonCached.Literal.INSTANCE);    
this.bind(CachingMyService.class).to(MyService.class)
    .in(Singleton.class).qualifiedBy(Cached.Literal.INSTANCE);

然后在注入它们时,添加适用的限定符

@Inject
@NonCached
MyService service;

@Inject
@Cached
MyService service;