弹簧 IoC 和通用接口类型

我正在尝试使用带有以下接口的Spring IoC:

public interface ISimpleService<T> {
    void someOp(T t);
    T otherOp();
}

Spring能否提供基于泛型类型参数T的IoC?我的意思是,像这样:

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

    @Autowired
    ISimpleService<String> strSvc;
    //...
}

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

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)

我的问题:是否可以提供类似的功能,同时对接口或实现类进行最少的修改?例如,我知道我可以使用@Qualifiers,但我想让事情尽可能简单。


答案 1

由于擦除,我认为这是不可能的。在进行全自动布线时,我们通常切换到强类型子接口:

public interface LongService extends ISimpleService<Long> {}
public interface StringService extends ISimpleService<String> {}

在进行此切换时,我们发现我们实际上非常喜欢它,因为它允许我们更好地进行“查找使用情况”跟踪,这是通用接口所缺少的。


答案 2

我不认为没有限定符就不可能

生病尝试用通用DAO显示我的解决方案,抱歉,如果它有点详细

接口和实现类定义

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

弹簧豆的定义,注意抽象=“真”

<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>

使用此泛型DAO而不使用特殊的实现类

 <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>

请注意带有具体类的构造函数-arg,如果您使用Spring Annotation,则需要执行以下操作:

@Autowired
@Qualifier(value = "testHibernateChildDao")
private GenericDAO<TOChild, Integer> ToChildDAO;

以区分通用道豆的各种版本(请注意直接引用豆名的限定符)

将此泛型DAO与特殊实现类一起使用

接口和类

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

豆定义,请注意上面对抽象泛型DAO的“父”引用

<bean id="testHibernateParentDao" class="de.optimum24.av.pers.test.hibernate.dao.TestHibernateParentDAOImpl"
      parent="genericHibernateDAO" />

和弹簧注释的用法

@Autowired
private TestHibernateParentDAO ToParentDAO;