自动装配依赖项注入失败,针对抽象类。

4

我是使用Spring 3和Hibernate 4

我有以下的类结构

public interface GenericDAO<T> {

    public void create(T entity);
    public void update(T entity);
    public void delete(T entity);
}

DAO class

public interface EmployeeDAO extends GenericDAO<Employee>  {

    public void findEmployee(EmployeeQueryData data);
}

DAO实现类

@Repository("employeeDAO")
public abstract class EmployeeDAOImpl implements EmployeeDAO {

protected EntityManager entityManager;

@Override
public void findEmployee(EmployeeQueryData data) {

...... code

}

我遇到的问题是在部署时出现以下异常。如果我从EmployeeDAOImpl中删除abstract并从EmployeeDAO中删除extends GenericDAO<Employee>,则应用程序可以无错误地部署。因此,在DAO实现中无法拥有EmployeeDAOImplabstract类,或者我需要在DAO实现中实现所有GenericDAO的方法而没有abstract
Error creating bean with 
name 'employeeService': Injection of autowired dependencies failed; \
nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: test.dao.EmployeeDAO 
test.service.EmployeeServiceImpl.employeeDAO; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No matching bean of type [test.dao.EmployeeDAO] found for dependency: 
expected at least 1 bean which qualifies as autowire candidate for 
this dependency. Dependency annotations: 
{@javax.inject.Inject()}.

Edit 1

GenericDAOImpl

public class GenericDAOImpl<T> implements GenericDAO<T> {    

    public void create(T entity) {
    }       
    public void update(T entity) {
    }
    public void delete(T entity) {
    }

EmployeeDAOImpl

public class EmployeeDAOImpl extends GenericDAOImpl<Employee> implements EmployeeDAO {

2
你不能创建抽象类的实例(bean),这是Java规范。创建abstract GenericDAOImpl<T> implements GenericDAO<T>,并实现它,然后从GenericDAOImpl<Employee>继承EmployeeDAOImpl - user1516873
@user1516873 类似于findEmployee的方法是特定于Employee实体和EmployeeDAO的。将其包含在GenericDAOImpl中是个好主意吗? - Jacob
通常我会在通用DAO中添加CRUD方法,例如findById、findAll和removeById。其他的方法则应该放在特定领域对象的接口/实现中。在你的情况下,findEmployee明显应该在EmployeeDAO而不是GenericDAO中。 - user1516873
@user1516873,你的意思是说创建、更新和删除应该针对实体或领域进行特定设计? - Jacob
1
CRUD操作很常见,可以移动到通用类中。因此它是领域特定的。当然,如果需要的话,您可以在实体特定的DAO中覆盖它。 - user1516873
@user1516873 我已经创建了 GenericDAOImpl<T>,在 EmployeeDAOImpl 中,我通过以下方式扩展 GenericDAOImpl 并实现 EmployeeDAOpublic class EmployeeDAOImpl extends GenericDAOImpl<Employee> implements EmployeeDAO { - Jacob
3个回答

3

Java(因此也包括Spring)无法创建抽象类的实例:每个方法在Java允许您创建实例之前都必须有一个实现,否则当您尝试调用该方法时会出现运行时错误。您需要从EmployeeDAOImpl中删除“abstract”并实现从GenericDAO继承的方法。


Stephen So,将GenericDAO的所有方法都实现在EmployeeDAOImpl中是否是最佳实践?因为create、update和delete是所有DAO类的通用方法且具有通用类型。 - Jacob
有各种模式可供选择,但它们都不是特别好的解决方案。在Java 8中,您将能够为接口定义默认实现(类似于mixin),这将使其变得更加容易。同时,您可以创建一个抽象的GenericDOAImpl,提供CRUD的默认实现,然后让EntityDAOImpl扩展GenericDOAImpl。 - Stephen Nelson
Stephen,我已经按照我的问题中的编辑1修改了EmployeeDAOImplGenericDOAImpl,请看一下。谢谢。 - Jacob

2
为什么要声明一个类实现为抽象类?从概念上讲这是一种矛盾。显然,Spring无法实例化它并失败了。

1

请确认您的EmployeeDAOImpl或其他已注释的类包是否在spring context xml文件中的以下标签中被提及。如果未完成此操作,则注释将不会被读取和初始化。

<context:component-scan base-package="com.app.service" />

是的,它在applicationContext.xml中执行包扫描。 - Jacob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接