Spring 3 DI使用通用DAO接口

时间:2010-05-17 06:52:26

标签: spring interface dependency-injection annotations autowired

我正在尝试将@Autowired注释与我的通用Dao界面一起使用,如下所示:

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

我以下列方式在Controller中使用此界面:

@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)}

现在,我有点困惑,我应该如何进行或者甚至可以使用多个Dao。任何帮助将不胜感激:)

2 个答案:

答案 0 :(得分:2)

好的,我认为我找到了一个相当合理的解决方案。解决这个问题的一种方法是为我的域模型中的每个实体创建接口和实现(正如Espen在之前的回答中指出的那样)。现在,考虑拥有数百个实体和数百个实现。那感觉不对,是吗?

我已经丢弃了强类型的子接口,而是使用通用接口:

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

所以基本上我无法使用纯通用自动装配工作,但这个解决方案适合我(至少现在):)

答案 1 :(得分:0)

可以根据需要自动装配多个bean。

但是当你按类型使用自动装配时,它只能是每个接口的bean之一。您的错误消息表明您在给定接口的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之类的专业化。

还要记住在com.organization.sample包中包含所有Spring组件,以使Spring容器能够找到它们。

我希望这有帮助!