Подтвердить что ты не робот

Spring IoC и общий тип интерфейса

Я пытаюсь использовать Spring IoC с таким интерфейсом:

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

Может ли Spring предоставлять IoC на основе аргумента типового типа T? Я имею в виду, что-то вроде этого:

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, но я хочу, чтобы все было как можно проще.

4b9b3361

Ответ 1

Я не считаю, что это возможно из-за стирания. Обычно мы переходим к строго типизированным суб-интерфейсам при полнофункциональной автоподготовке:

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

После этого мы обнаружили, что нам это очень понравилось, потому что это позволяет нам намного лучше отслеживать "поиск использования", что вы теряете с помощью интерфейсов generics.

Ответ 2

Я не думаю, что это возможно без Qualifier

плохо попробуйте показать мои решения с 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;
    }

определение 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>

Обратите внимание на конструктор-arg с конкретным классом, если вы работаете с spring Аннотации, которую вам нужно сделать:

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

чтобы различать различные версии genericDao Beans (обратите внимание на Qualifier с прямой ссылкой на Beanname)

Использование этого genericDAO со специальной реализацией Class

Интерфейс и класс

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 Аннотация

@Autowired
private TestHibernateParentDAO ToParentDAO;

Ответ 3

Это можно сделать с помощью стирания, если общий тип полностью подтвержден во время компиляции. В этом случае информация о типе доступна через любой из:

Class#getGenericInterfaces()
Class#getGenericSuperclass()

Это основная особенность Guice, которая отсутствует в Spring.

Ответ 4

Не делайте свой общий интерфейс. Вместо этого создайте свои методы:

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

Надеюсь, что это поможет.

Ответ 5

При выполнении этого с некоторыми уровнями сохранения, Spring Данные делает это для вас. Spring Данные - действительно отличный инструмент для экономии времени и упрощения, если вы используете JPA, Neo4j или MongoDB, или что-то еще, что оно поддерживает.

Ответ 6

Другой вариант - аннотировать интерфейс, реализующий 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;