web-dev-qa-db-ja.com

Spring IoCおよびGeneric Interface Type

私はこのようなインターフェイスで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を使用できることはわかっていますが、できる限りシンプルにしたいと考えています。

36
Miguel Ping

消去が原因でこれが可能であるとは思わない。全自動配線を行う場合、通常、強く型付けされたサブインターフェースに切り替えました。

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

この切り替えを行ったところ、実際にこれが非常に気に入っていることがわかりました。これにより、ジェネリックインターフェイスで緩やかな「使用状況の検索」をより適切に追跡できるようになるためです。

24
krosenvold

修飾子なしではそれは不可能だと思います

ジェネリック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;
    }

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>

特別な実装クラスなしでこの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>

具体的なクラスを持つコンストラクタ引数に注意してください。SpringAnnotationを使用する場合は、次のことを行う必要があります。

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

genericDao Beanのさまざまなバージョンを区別する(Bean名を直接参照する修飾子に注意してください)

特別な実装クラスでこの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定義。上記の抽象genericDAOへの「親」参照に注意してください

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

およびSpring Annotationでの使用

@Autowired
private TestHibernateParentDAO ToParentDAO;
14
Michael Pralow

ジェネリック型がコンパイル時に完全に具体化されている場合は、これを消去して行うことができます。この場合、タイプ情報は次のいずれかから入手できます。

Class#getGenericInterfaces()
Class#getGenericSuperclass()

これは春に欠けているGuiceの主要な機能です。

4
JasonQR

インターフェイスをジェネリックにしないでください。代わりにメソッドを作成してください:

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

それが役に立てば幸い。

3
Razvan

特定の永続化レイヤーでこれを行う場合、 Spring Data がこれを行います。 Spring Dataは、JPA、Neo4j、MongoDB、またはそれがサポートする何かを使用している場合、時間の節約と簡素化に非常に優れたツールです。

0
CorayThan

もう1つのオプションは、インターフェース実装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;
0
s0vet