Spring 3 DI с помощью универсального интерфейса DAO

Я пытаюсь использовать @Autowired аннотацию со своим универсальным интерфейсом Dao как это:

public interface DaoContainer<E extends DomainObject> {
    public int numberOfItems();
    // Other methods omitted for brevity 
}

Я использую этот интерфейс в своем Контроллере следующим способом:

@Configurable
public class HelloWorld {
    @Autowired
    private DaoContainer<Notification> notificationContainer;

    @Autowired
    private DaoContainer<User> userContainer;

    // Implementation omitted for brevity
}

Я настроил свой контекст приложения со следующей конфигурацией

<context:spring-configured />
<context:component-scan base-package="com.organization.sample">
<context:exclude-filter expression="org.springframework.stereotype.Controller"
   type="annotation" />
</context:component-scan>
<tx:annotation-driven />

Это работает только частично, так как Spring создает и вводит только один экземпляр моего DaoContainer, а именно, DaoContainer. Другими словами, если я спрашиваю userContainer.numberOfItems (); я получаю количество notificationContainer.numberOfItems ()

Я попытался использовать интерфейсы со строгим контролем типов для маркировки корректной реализации как это:

public interface NotificationContainer extends DaoContainer<Notification> { }
public interface UserContainer extends DaoContainer<User> { }

И затем используемый эти интерфейсы как это:

@Configurable
public class HelloWorld {
    @Autowired
    private NotificationContainer notificationContainer;
    @Autowired
    private UserContainer userContainer;
    // Implementation omitted...
}

Печально это перестало работать к BeanCreationException:

org.springframework.beans.factory.BeanCreationException: Could not autowire field:   private com.organization.sample.dao.NotificationContainer com.organization.sample.HelloWorld.notificationContainer; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.organization.sample.NotificationContainer] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Теперь, я немного смущен, как я должен продолжить двигаться или использую несколько Дао, даже возможный. Любая справка значительно ценилась бы :)

7
задан Peders 17 May 2010 в 06:52
поделиться

2 ответа

Можно автоматически подключить столько компонентов, сколько захотите.

Но когда вы используете автоматическое подключение по типу, это может быть только один компонент каждого интерфейса. В вашем сообщении об ошибке говорится, что в контейнере Spring данного интерфейса нет доступного bean-компонента.

Решение:

Ваши недостающие реализации DAO:

@Repository
public class NotificationContainerImpl implements NotificationContainer {}

@Repository
public class UserContainerImpl implements UserContainer {}

Ваш класс обслуживания:

@Service
public class HelloWorld {
    @Autowired
    private NotificationContainer notificationContainer;
    @Autowired
    private UserContainer userContainer;
    // Implementation omitted...
}

Я заменил аннотацию @Configurable на @Service . @Configurable используется вместе с AspectJ, и это не то, что вам здесь нужно. Вы должны использовать @Component или его специализацию, например @Service .

Также не забудьте, что все ваши компоненты Spring должны находиться внутри вашего пакета com.organization.sample , чтобы контейнер Spring мог их найти.

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

0
ответ дан 7 December 2019 в 18:40
поделиться

Хорошо, я думаю, что нашел довольно разумное решение этой головоломки. Один из способов справиться с этим - создать интерфейс и реализации для каждой сущности в моей модели предметной области (как ранее указал Эспен в своем ответе). Теперь рассмотрим наличие сотен сущностей и, соответственно, сотен реализаций. Это было бы неправильно, не так ли?

Я отказался от строго типизированных субинтерфейсов и вместо этого использую общий интерфейс:

@Service // Using @Service annotation instead @Configurable as Espen pointed out
public class HelloWorld {
    @Autowired
    private DaoContainer<Notification> notificationContainer;

    @Autowired
    private DaoContainer<User> userContainer;

    // Implementation omitted
}

Реализация моего интерфейса DaoContainer будет выглядеть примерно так:

@Repository
public class DaoContainerImpl<E extends DomainObject> implements DaoContainer<E> {

    // This is something I need in my application logic
    protected Class<E> type;

    public int getNumberOfItems() {
       // implementation omitted
    }
    // getters and setters for fields omitted

}

И, наконец, контекст приложения:

<context:spring-configured />
<context:component-scan base-package="com.organization.sample">
<context:exclude-filter expression="org.springframework.stereotype.Controller"
    type="annotation" />
</context:component-scan>

<bean class="com.organization.sample.dao.DaoContainerImpl" id="userContainer">
    <property name="type" value="com.organization.sample.domain.DiaryUser" />
</bean>
<bean class="com.organization.sample.dao.DaoContainerImpl" id="notificationContainer">
    <property name="type" value="com.organization.sample.domain.DiaryNotification" />
</bean>

По сути, я не мог заставить работать обычную автоматическую проводку, но это решение работает для меня (по крайней мере, на данный момент):)

2
ответ дан 7 December 2019 в 18:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: