Spring IoC和通用接口类型

Mig*_*ing 36 java generics spring types inversion-of-control

我正在尝试使用Spring IoC这样的接口:

public interface ISimpleService<T> {
    void someOp(T t);
    T otherOp();
}
Run Code Online (Sandbox Code Playgroud)

Spring可以根据泛型类型参数T提供IoC吗?我的意思是,像这样:

public class SpringIocTest {
    @Autowired
    ISimpleService<Long> longSvc;

    @Autowired
    ISimpleService<String> strSvc;
    //...
}
Run Code Online (Sandbox Code Playgroud)

当然,我上面的例子不起作用:

expected single matching bean but found 2: [serviceLong, serviceString]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessAfterInstantiation(AutowiredAnnotationBeanPostProcessor.java:243)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:957)
Run Code Online (Sandbox Code Playgroud)

我的问题:是否可以提供类似的功能,只需对接口或实现类进行最少的修改?我知道我可以使用@Qualifiers,但我希望尽可能简单.

kro*_*old 24

由于擦除,我不相信这是可能的.在进行全自动装配时,我们通常会切换到强类型子接口:

public interface LongService extends ISimpleService<Long> {}
public interface StringService extends ISimpleService<String> {}
Run Code Online (Sandbox Code Playgroud)

在进行此切换时,我们发现我们实际上非常喜欢这个,因为它允许我们更好地"查找使用"跟踪,使用泛型接口松散.


Mic*_*low 14

如果没有资格赛,我不认为这是可能的

我试着用genericDAO展示我的解决方案,对不起,如果它有点详细

接口和实现类定义

public interface GenericDAO<T, ID extends Serializable> (...)

public class GenericDAOImpl<T, ID extends Serializable>
    implements GenericDAO<T, ID> 
    (...) important is this constructor
    public GenericDAOImpl(Class<T> persistentClass) {
       this.persistentClass = persistentClass;
    }
Run Code Online (Sandbox Code Playgroud)

spring bean定义,注意abstract ="true"

<bean id="genericHibernateDAO" class="de.optimum24.av.pers.ext.hibernate.dao.GenericDAOImpl"
      abstract="true">
    <description>
        <![CDATA[
            Definition des GenericDAO.
        ]]>
    </description>
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
Run Code Online (Sandbox Code Playgroud)

使用此genericDAO无需特殊实现类

 <bean id="testHibernateChildDao" class="de.optimum24.av.pers.ext.hibernate.dao.GenericDAOImpl">
    <property name="sessionFactory" ref="sessionFactory" />
    <constructor-arg>
        <value>de.optimum24.av.pers.test.hibernate.domain.TOChild</value>
    </constructor-arg>
</bean>
Run Code Online (Sandbox Code Playgroud)

注意带有具体类的constructor-arg,如果你使用Spring Annotation,你需要做:

@Autowired
@Qualifier(value = "testHibernateChildDao")
private GenericDAO<TOChild, Integer> ToChildDAO;
Run Code Online (Sandbox Code Playgroud)

区分genericDao Beans的各种版本(注意限定符直接引用Beanname)

将此genericDAO与特殊实现类一起使用

接口和类

public interface TestHibernateParentDAO extends GenericDAO<TOParent, Integer>{
  void foo();
}
public class TestHibernateParentDAOImpl extends GenericDAOImpl<TOParent, Integer>
                              implements TestHibernateParentDAO {
  @Override
  public void foo() {
      //* no-op */
  }
}
Run Code Online (Sandbox Code Playgroud)

Bean定义,请注意上面的抽象genericDAO的"父"参考

<bean id="testHibernateParentDao" class="de.optimum24.av.pers.test.hibernate.dao.TestHibernateParentDAOImpl"
      parent="genericHibernateDAO" />
Run Code Online (Sandbox Code Playgroud)

和Spring Annotation的用法

@Autowired
private TestHibernateParentDAO ToParentDAO;
Run Code Online (Sandbox Code Playgroud)