How to collect several interfaces into a Collection in HK2?

不羁的心 提交于 2019-12-11 10:13:16

问题


I have my AbstractBinder and I bind several classes with the same interface. Let's say I bind Fish and Cat which both implement Animal interface.

What is the easiest/proper way of injecting them into a bean which takes Collection<Animal> ?

PS: Spring has equivalent in simply @Autowire List<Animal> and the collection is created and populated by Spring.


回答1:


HK2 has IterableProvider<T>, as mentioned here in the documentation. You can get the service by name, by qualifier annotation, or just iterate over them, as it's an Iterable. Just for fun, here is a test.

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);  
    }
}

UPDATE

For a List<Service> (to avoid HK2 InterablProvider), the only think I can think of is to use a Factory and inject the IterableProvider into it, and from there return the list. For example

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) {}
}

Yeah it's a little bit of extra work.




回答2:


In the latest release of hk2 (2.4.0) you can

@Inject Iterable<Foo> foos;

That allows you to keep your pojo's without any hk2 API in them.

For more information see: Iterable Injection



来源:https://stackoverflow.com/questions/34021935/how-to-collect-several-interfaces-into-a-collection-in-hk2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!