HK2中如何将多个接口收集到一个Collection中?

How to collect several interfaces into a Collection in HK2?

我有我的 AbstractBinder 并且我用相同的界面绑定了多个 类。假设我绑定了 FishCat ,它们都实现了 Animal 接口。

将它们注入需要 Collection<Animal> 的 bean 的 easiest/proper 方法是什么?

PS:Spring 等价于 @Autowire List<Animal>,集合由 Spring.

创建和填充

HK2 有 IterableProvider<T>, as mentioned here in the documentation. You can get the service by name, by qualifier annotation,或者只是迭代它们,因为它是一个 Iterable。只是为了好玩,这里有一个测试。

public class IterableProviderTest {
    
    public static interface Service {}
    
    public static class ServiceOne implements Service {}
    
    @QualAnno
    public static class ServiceTwo implements Service {}
    
    @Qualifier
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public static @interface QualAnno {
        public static class Instance 
                extends AnnotationLiteral<QualAnno> implements QualAnno {
            public static QualAnno get() {
                return new Instance();
            }
        }
    }
    
    public class Binder extends AbstractBinder {
        @Override
        protected void configure() {
            bind(ServiceOne.class).to(Service.class).named("one");
            bind(ServiceTwo.class).to(Service.class).qualifiedBy(QualAnno.Instance.get());
        }  
    }
    
    @Inject
    private IterableProvider<Service> services;
    
    @Test
    public void test_IterableProvider() {
        ServiceLocator locator = ServiceLocatorUtilities.bind(new Binder());
        locator.inject(IterableProviderTest.this);
        
        assertEquals(2, services.getSize());
        
        Service serviceOne = services.named("one").get();
        assertTrue(serviceOne instanceof ServiceOne);
        
        Service serviceTwo = services.qualifiedWith(QualAnno.Instance.get()).get();
        assertTrue(serviceTwo instanceof ServiceTwo);  
    }
}

更新

对于 List<Service>(避免 HK2 InterablProvider),我唯一能想到的就是使用 Factory 并将 IterableProvider 注入其中,然后从那里 return 列表。例如

public class Binder extends AbstractBinder {
    @Override
    protected void configure() {
        ...
        bindFactory(ListServiceFactory.class).to(new TypeLiteral<List<Service>>(){});
    }  
}

public static class ListServiceFactory implements Factory<List<Service>> {
    
    @Inject
    private IterableProvider<Service> services;

    @Override
    public List<Service> provide() {
        return Lists.newArrayList(services);
    }

    @Override
    public void dispose(List<Service> t) {}
}

是的,这是一些额外的工作。

在最新版本的hk2(2.4.0)中可以

@Inject Iterable<Foo> foos;

这样您就可以保留没有任何 hk2 API 的 pojo。

有关详细信息,请参阅:Iterable Injection