【问题标题】:java.lang.Class cannot be cast to java.lang.reflect.ParameterizedTypejava.lang.Class 不能强制转换为 java.lang.reflect.ParameterizedType
【发布时间】:2012-06-16 22:22:47
【问题描述】:

我被这个问题困扰了很长时间。我搜索了这个问题一段时间,但没有一个解决方案有效。

结构:

public interface GenericDAO<T extends Serializable, ID extends Serializable>

@Repository
public class AbstractGenericDAO<T extends Serializable, ID extends Serializable> 
    implements GenericDAO<T, ID> {

   private Class<T> persistentClass;

   @Autowired
   private SessionFactory sessionFactory;

   static Logger LOGGER = Logger.getLogger(AbstractGenericDAO.class);


   @SuppressWarnings("unchecked")
   public AbstractGenericDAO() {
       this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
   }

   /**
    * @param entity
    * @return T
    * @throws DBException
    */
   @SuppressWarnings("unchecked")
   public T saveEntity(T entity) throws DBException {
       return saveEntity(entity, false);
   }

   /**
    * @param entity
    * @param explicitFlush
    * @return T
    * @throws DBException
    */
   @SuppressWarnings("unchecked")
   public T saveEntity(T entity, boolean explicitFlush) throws DBException {
       Session session = getSessionFactory().getCurrentSession();

       try {
           session.save(entity);
           if(explicitFlush) {
               session.flush();
               session.refresh(entity);
           }
       } catch (HibernateException he) {
           String errorMsg = "Could not save entity. Reason: " + he.getMessage();
           LOGGER.error(errorMsg, he);
           throw new DBException(errorMsg, he);
       }

       return entity;
   }

   /* (non-Javadoc)
    * @see com.amazon.fc.receive.dbaccess.dao.GenericDAO#getPersistentClass()
    */
   @SuppressWarnings("unchecked")
   public Class<T> getPersistentClass() {
       return persistentClass;
   }

   /**
    * @return the sessionFactory
    */
   public SessionFactory getSessionFactory() {
       return this.sessionFactory;
   }

   /**
    * @param sessionFactory the sessionFactory to set
    */
   @Autowired
   public void setSessionFactory(SessionFactory sessionFactory) {
       this.sessionFactory = sessionFactory;
   }
}

public interface ShlkActiveWorkflowDAO 
    extends GenericDAO<ShlkActiveWorkflow, Serializable> 

@Repository
public class ShlkActiveWorkflowDAOImpl 
    extends AbstractGenericDAO<ShlkActiveWorkflow, Serializable>
    implements ShlkActiveWorkflowDAO

我也在我的application-config.xml 中使用&lt;context:component-scan&gt; + &lt;tx:annotation-driven /&gt; 在我的application-config.xml 中。

请提供一些有关如何解决此问题的信息。

Exception:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'abstractGenericDAO' 

Constructor threw exception; nested exception is java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:946)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:890)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:479)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:290)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:287)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:189)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:557)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:842)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:416)
    at com.coral.spring.Launcher.<init>(Launcher.java:95)
    at com.coral.spring.Launcher.main(Launcher.java:56)
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.workflow.dao.AbstractGenericDAO]: Constructor threw exception; nested exception is     
java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:141)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:72)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:938)
    ... 12 more
Caused by: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
    at com.workflow.dao.AbstractGenericDAO.<init>(AbstractGenericDAO.java:43)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:126)
    ... 14 more

【问题讨论】:

  • 我们需要更多来自类 com.workflow.dao.AbstractGenericDAO 的代码
  • 你真的需要AbstractGenericDAO@Repository 注释吗?从您的体系结构看来,注入更专业的类型才有意义。请记住,根据定义,每个Repository 都是可以连接的@Component
  • 我刚刚为 AbstractGenericDAO.java 添加了一些代码
  • 那我应该改用@Component 吗?

标签: java spring


【解决方案1】:

AbstractGenericDAO中删除@Repository注解,改成abstract

public abstract class AbstractGenericDAO<T extends Serializable, ID extends Serializable> 
   implements GenericDAO<T, ID>

出现您的问题是因为@Repository@Component 的特化,这意味着Spring 将尝试创建AbstractGenericDAO 实例进行注入。由于AbstractGenericDAO 超类 (Object) 不是通用的,您将无法将其Type 向下转换为ParameterizedType,因此这行代码将失败(与您尝试用new AbstractGenericDAO()手动实例化它):

this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];

专用类ShlkActiveWorkflowDAOImpl 仍应使用@Repository 进行注释。当 spring 尝试创建此类的实例时,将隐式调用 AbstractGenericDAO 构造函数,但这一次上面提到的代码行将按预期运行。发生这种情况是因为getClass() 返回ShlkActiveWorkflowDAOImpl.class,它是通用AbstractGenericDAO 的子类(所以向下转换为ParameterizedType 有效)。

由于ShlkActiveWorkflowDAOImpl extends AbstractGenericDAO&lt;ShlkActiveWorkflow, Serializable&gt; 实际类型ShlkActiveWorkflow 将在运行时正确反映。这是避免将Class&lt;T&gt; 引用传递给AbstractGenericDAO 构造函数的已知解决方法。

如果您担心AbstractGenericDAO 处的@Autowired 注释,请不要担心。当您注入其子类之一的实例时,Spring 将正确连接所有内容。

【讨论】:

  • 谢谢。这工作正常,但是当我在 ShlkActiveWorkflowDAOImpl 中添加了一个注释时,我得到了同样的异常。
  • 我在 ShlkActiveWorkflowDAOImpl 的一种方法中添加了内部注释'@Timed'
  • 我认为您应该为此错误打开一个新主题。无论如何,您不应该在开发层中使用@Timed 和其他测试注释。创建一个单独的testing 层并注入您的对象(或模拟)。
  • 我将为此打开一个单独的主题。但“@Timed”不适用于测试。这是我们对指标的注释。
  • 我以为你指的是org.springframework.test.annotation.Timed,它是专门用于测试的。
【解决方案2】:
Type genericSuperClass = getClass().getGenericSuperclass();

ParameterizedType parametrizedType = null;
while (parametrizedType == null) {
   if ((genericSuperClass instanceof ParameterizedType)) {
       parametrizedType = (ParameterizedType) genericSuperClass;
   } else {
       genericSuperClass = ((Class<?>) genericSuperClass).getGenericSuperclass();
   }
}

this.itemClass = (Class<T>) parametrizedType.getActualTypeArguments()[0];

【讨论】:

  • 为什么是负分? cglib可能是spring代理了AbstractGenericDAO类,所以我们需要检查层次结构
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-29
  • 2012-05-22
  • 2016-09-27
  • 1970-01-01
  • 2015-09-03
  • 2019-06-09
相关资源
最近更新 更多