2009-02-02 209 views
35

我試圖使用Spring IoC和像這樣的接口:的Spring IoC和泛型接口類型,

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

春天基於通用類型參數牛逼提供的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

現在看來是可能的,因爲春季4.0。看到[SO回答](http://stackoverflow.com/a/22603321/196533)和Spring文章[Spring Framework 4.0和Java泛型](http://spring.io/blog/2013/12/03 /彈簧框架-4-0和 - java的泛型)。 – chrisjleu 2014-11-09 21:43:36

回答

22

我不認爲這是可能的,因爲擦除。我們一般交換去爲全自動裝配時,強類型的子接口:

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

在做這個開關,我們發現我們真的喜歡這很好,因爲它允許我們做「找到使用」跟蹤好得多,你用泛型接口放鬆了一些東西。

+1

你如何處理代碼重複?可能有一個也是通用的中產階級,不是嗎? Tks – 2009-02-02 12:49:55

+0

唯一需要的重複是標記界面。但是你沒有顯示你的實現類,所以我不能告訴你是否正在做我沒有看到的任何事情! – krosenvold 2009-02-02 12:52:57

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

春豆的定義,注意摘要=「真」

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

使用這種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> 

通知構造 - 精氨酸與具體的類,如果你使用Spring註釋工作,你需要做的:

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

區分各種版本(注意限定詞直接引用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 */ 
    } 
} 

bean定義,請注意以上

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

和使用 「父」 參考了抽象genericDAO與Spring註釋

@Autowired 
private TestHibernateParentDAO ToParentDAO; 
3

不要讓你的接口是通用的。讓你的方法,而不是:

public interface ISimpleService { 
    public <T> T doSomething(T param); 
} 

希望它有幫助。

4

如果通用類型在編譯時被完全泛化,那麼可以通過擦除來完成。在這種情況下,類型信息通過任一可用:

Class#getGenericInterfaces() 
Class#getGenericSuperclass() 

這是從春天缺少吉斯的主要特點。

0

當對某些持久層進行此操作時,Spring Data會爲您執行此操作。如果您使用的是JPA,Neo4j或MongoDB,或者它支持的其他東西,那麼Spring Data是一個非常節省時間和簡化的工具。

0

另一種選擇是註釋一側實現與名的bean接口,並預選賽指向創建的名稱的另一邊註釋:)下面是一個簡單的例子,我用我的項目:

public interface IDAO<T> { 

     public void insert(T model); 
     public void update(T model); 
     public void delete(T model); 
    } 

抽象類的前身:

public abstract class AbstractHibernateDAO { 

     protected SessionFactory sessionFactory; 

     protected Session currentSession() { 
      return sessionFactory.getCurrentSession(); 
     } 
    } 

爲實體用戶實現抽象類:

@Repository(value = "userRepository") 
public class UserDAO extends AbstractHibernateDAO implements IDAO<User> { 

    @Autowired 
    public UserDAO(SessionFactory sessionFactory) { 
     this.sessionFactory = sessionFactory; 
    } 

    @Override 
    public void insert(User user) { 
     currentSession().save(user); 
    } 

    @Override 
    public void update(User user) { 
     currentSession().update(user); 
    } 

    @Override 
    public void delete(User user) { 
     currentSession().delete(user); 
    } 

}

最後注入正確的實現:

@Resource 
@Qualifier(value = "userRepository") 
IDAO<User> userPersistence;