2012-06-16 21 views
12

Tengo este problema durante mucho tiempo. Busqué este problema por algún tiempo, pero ninguna de las soluciones funcionó.java.lang.Class no se puede convertir a java.lang.reflect.ParameterizedType

Estructura:

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 

También estoy usando <context:component-scan> en mi application-config.xml + <tx:annotation-driven /> en mi application-config.xml.

Proporcione información acerca de cómo solucionar este problema.

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 
+0

Necesitamos más código de la clase ** ** com.workflow.dao.AbstractGenericDAO –

+0

lo que realmente necesita 'AbstractGenericDAO' a ser anotada con' @ Repository'? Desde su arquitectura, parece que solo tiene sentido inyectar el tipo más especializado. Recuerde que cada [Repositorio] (http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/stereotype/Repository.html) es por definición un '@ Component' que se puede conectar. –

+0

Acabo de agregar un código para AbstractGenericDAO.java – user864077

Respuesta

14

Retire @Repository anotación de AbstractGenericDAO y hacerla abstract:

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

Su problema se produce porque @Repository es una especialización de @Component, lo que significa que la primavera va a tratar de crear AbstractGenericDAO instancias para inyección. Como la superclase AbstractGenericDAO (Object) no es genérica, no podrá descifrar su Type a ParameterizedType, por lo que esta línea de código fallará (de la misma forma que lo haría si intentara crear una instancia manualmente con new AbstractGenericDAO()):

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

La clase especializada ShlkActiveWorkflowDAOImpl aún debe ser anotado con @Repository. Cuando Spring intenta crear una instancia de esta clase, se producirá una llamada implícita al constructor AbstractGenericDAO, pero esta vez la línea de código mencionada anteriormente se ejecutará como se esperaba. Esto ocurre porque getClass() devuelve ShlkActiveWorkflowDAOImpl.class que es una subclase del genérico AbstractGenericDAO (por lo que el downcast a ParameterizedType funciona).

Desde ShlkActiveWorkflowDAOImplextendsAbstractGenericDAO<ShlkActiveWorkflow, Serializable> el tipo real ShlkActiveWorkflow se reflejará correctamente en el tiempo de ejecución. Esta es una solución conocida para evitar pasar una referencia Class<T> al constructor AbstractGenericDAO.

Si le preocupa la anotación @Autowired en AbstractGenericDAO, no lo haga. Spring conectará correctamente todo cuando inyecte una instancia de una de sus subclases.

+0

Gracias. Esto funciona bien, pero cuando agregué una anotación más dentro de ShlkActiveWorkflowDAOImpl, recibo la misma excepción. – user864077

+0

He agregado la anotación interna '@Timed' dentro de uno de los métodos de ShlkActiveWorkflowDAOImpl – user864077

+0

Creo que deberías abrir un nuevo tema para este error. De todos modos, no deberías usar '@ Timed' y otras anotaciones de prueba en tu capa de desarrollo. Cree una [prueba] por separado (http://static.springsource.org/spring/docs/3.0.x/reference/testing.capa de html # unit-testing) e inyecta tu objeto (o un simulacro). –

-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]; 
+0

¿por qué puntuación negativa? Es posible que la clase proxiada por resorte AbstractGenericDAO por cglib, entonces necesitamos jerarquía de verificación –

Cuestiones relacionadas