【问题标题】:Spring dependency injection generic service classSpring依赖注入通用服务类
【发布时间】:2015-01-20 13:02:29
【问题描述】:

我有一个通用的 dao 类,我正在尝试使用 spring 依赖注入,但出现以下错误

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'BaseDao' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.abgc.fab.dao.BaseDao]: Constructor threw exception; nested exception is java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class

我的 applicationContext.xml 文件

<bean id="BaseDao" class="com.abgc.fab.dao.BaseDao">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

我的基础课:

public class BaseDao<TEntity> extends CommonDao<TEntity> implements IBaseDao<TEntity> {

}

 public abstract class CommonDao<TEntity> extends FabObject implements ICommonDao<TEntity> { 
       public CommonDao() { 
               Type t = getClass().getGenericSuperclass();
               ParameterizedType pt = (ParameterizedType) t;           
                this.classEntity = (Class<TEntity>) pt.getActualTypeArguments()[0]; 
      }

有什么帮助吗?

【问题讨论】:

  • 它说明了构造函数抛出异常?构造函数是什么样的?
  • 还有CommonDao的构造函数?
  • 你能显示CommonDao吗?
  • 还有你用的是哪个春季版本?你在使用springs自动连接bean吗?
  • public abstract class CommonDao&lt;TEntity&gt; extends FabObject implements ICommonDao&lt;TEntity&gt; { public CommonDao() { Type t = getClass().getGenericSuperclass(); ParameterizedType pt = (ParameterizedType) t; this.classEntity = (Class&lt;TEntity&gt;) pt.getActualTypeArguments()[0]; }

标签: java spring dependency-injection dao


【解决方案1】:

TEntity 是一个实际的类还是你的类型参数?

在我看来,TEntity 只是您的类型参数的名称,我认为这不起作用。

你需要类似的东西

class ConcreteNominationHibernateDAO
    extends BaseDao<ConcreteNominationSubclass> {...}

【讨论】:

    【解决方案2】:

    如果层次结构较深,您需要使用 TypeTools 之类的东西:

    class DeviceDao extends BaseDao<Device> {}
    
    Class<?> entityType = TypeResolver.resolveRawArgument(IBaseDao.clas, DeviceDao.class);
    assert entityType == Device.class;
    

    注意:与往常一样,类型参数只有在类型定义中被捕获时才能在运行时解析。所以子类化BaseDao 是必要的。

    【讨论】:

      【解决方案3】:

      检查注解@Entity、@Service 等。也许你错过了一些东西。所以DAO类不能调用POJO类,bean也不能初始化。

      【讨论】:

        【解决方案4】:

        根据 javadoc,ParameterizedType.getActualTypeArguments 返回一个 Type[]Type 不一定是 Class,因此转换为 Class 是不安全的。

        根据 Piotr Findeisen 的回答 here

        表达式

        getClass().getGenericSuperclass()).getActualTypeArguments()[0]
        

        指代替换为AbstractHibernateDAO 的第一个类型参数的值(在AbstractHibernateDAO.java 中由T 表示)。子类NominationHibernateDAO替换的类型仍然不具体,它是T extends Nomination,这绝对不是java.lang.Class实例,而是Type实例(TypeVariableImplType的实现)。

        如果NominationHibernateDAO 是这样声明的:

        class NominationHibernateDAO extends AbstractHibernateDAO<Nomination, Integer> { ...
        

        那么AbstractHibernateDAO 构造函数的魔法就会起作用。或者,您可以(或者甚至应该?)实例化 NominationHibernateDAO 的子类,声明如下:

        class ConcreteNominationHibernateDAO
                extends NominationHibernateDAO<ConcreteNominationSubclass> { ...
        

        new NominationHibernateDAO<ConcreteNominationSubclass>() {}
        

        同样,这不会引发问题。

        您确定 NominationHibernateDAO 类是用作 Spring bean 的吗?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-09-09
          • 2019-09-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-31
          相关资源
          最近更新 更多