2012-05-14 18 views
8

Actualmente, VariableService es @Autowired en mi controlador.La clase no se puede convertir a java.lang.reflect.ParameterizedType

Me doy cuenta de que puedo implementar la clase ParameterizedType para hacer desaparecer este error, pero me temo que puedo estar yendo en la dirección incorrecta. ¿Hay una manera mejor de hacer esto o tengo que tomar la iniciativa e implementar los métodos de ParameterizedType?

org.springframework.beans.factory.BeanCreationException: Error al crear bean con el nombre 'contentController': error en la inyección de las dependencias de autocableado; la excepción anidada es org.springframework.beans.factory.BeanCreationException: no se pudo autoconectar el campo: privado com.fettergroup.cmt.service.VariableService com.fettergroup.cmt.web.ContentController.variableService; la excepción anidada es org.springframework.beans.factory.BeanCreationException: Error al crear bean con el nombre 'variableService' definido en el recurso ServletContext [/WEB-INF/dispatcher-servlet.xml]: Falló la instanciación del bean; La excepción anidada es org.springframework.beans.BeanInstantiationException: No se pudo crear una instancia de la clase bean [com.fettergroup.cmt.service.VariableService]: Constructor lanzó una excepción; la excepción jerarquizada es java.lang.ClassCastException: java.lang.Class no se puede convertir a java.lang.reflect.ParameterizedType

Servicio variable

public class VariableService extends EntityService { 
    public VariableService() { 
     super.setEntityRepository(new VariableRepository()); 
    } 
} 

EntityService

public abstract class EntityService<T> { 

    public EntityRepository<T> entityRepository; 

    public T create(T entity) { 
     return entityRepository.create(entity); 
    } 

    public T update(T entity) { 
     return entityRepository.update(entity); 
    } 

    public void delete(T entity) { 
     entityRepository.delete(entity); 
    } 

    public void setEntityRepository(EntityRepository<T> entityRepository) { 
     this.entityRepository = entityRepository; 
    } 
} 

Repositorio de variables

public class VariableRepository extends EntityRepository { 

} 

EntityRepository

@Repository 
public abstract class EntityRepository<T> { 

    //the equivalent of User.class 
    protected Class<T> entityClass; 

    @PersistenceContext(type= PersistenceContextType.TRANSACTION) 
    public EntityManager entityManager; 

    public EntityRepository() { 
     //Get "T" and assign it to this.entityClass 
     ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass(); 
     this.entityClass = (Class<T>) genericSuperclass.getActualTypeArguments()[0]; 
    } 

    /** 
    * Create this entity 
    * @param t 
    * @return 
    */ 
    public T create(T t) { 
     entityManager.persist(t); 
     return t; 
    } 

    /** 
    * Update this entity 
    * @param t 
    * @return 
    */ 
    public T update(T t) { 
     return entityManager.merge(t); 
    } 

    /** 
    * Delete this entity 
    * @param entity 
    */ 
    public void delete(T t) { 
     t = this.update(t); 
     entityManager.remove(t); 
    } 

    public void setEntityManager(EntityManager entityManager) { 
     this.entityManager = entityManager; 
    } 
} 

Respuesta

12

sólo decir, se trata de un diseño bastante pobre para determinar el tipo de entidad .. que debe hacer el siguiente lugar de depender de reflexión para inferir su definición de clase .. No sólo va a deshacerse de ese error, pero será más limpio en general y en un nivel bajo, más rápido que la reflexión (no es que realmente sea un problema).

@Repository 
public abstract class EntityRepository<T>{ 
    protected Class<T> entityClass; 

    public EntityRepository(Class<T> entityClass){ 
     this.entityClass = entityClass; 
    } 

    //... 
} 


public class UserEntityRepository extends EntityRepository<User>{ 
    public UserEntityRepository(){ 
     super(User.class); 
    } 
} 
+0

Solo quería decir que este es el enfoque de diseño que uso para mi capa de acceso a datos. Déjeme saber si usted tiene preguntas. – Atticus

+1

¿puede la primavera autoautar la entidadClass de esta manera? –

2

Parece que usted está haciendo un mal uso ParameterizedType. En el constructor EntityRepository, debe usar algo como lo siguiente, con las comprobaciones apropiadas.

public EntityRepository() { 
    //Get "T" and assign it to this.entityClass 
    ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass(); 
    Type type = genericSuperclass.getActualTypeArguments()[0]; 
    if (type instanceof Class) { 
     this.entityClass = (Class<T>) type; 
    } else if (type instanceof ParameterizedType) { 
     this.entityClass = (Class<T>) ((ParameterizedType)type).getRawType(); 
    } 
} 

Esta implementación está lejos de ser completa, aunque, como también se debe manejar GenericArrayType valores, así como anidado ParameterizedType.

+0

añadí su contenido e importados 'java.lang.reflect.Type;' y 'type' no tiene el método' getRawType() ' – Webnet

+0

Ah, me olvidaba un molde. It 'type' es del tipo' ParameterizedType', tienes que convertirlo a 'ParameterizedType' para llamar a' getRawType() '. – tonio

5

EntityRepository no tiene el tipo de parámetro parametrizado. Esta clase solo extiende ParameterizedType.Esto también es posible si la primavera se aproxima clase cglib

Necesitamos comprobar padres de clase

public EntityRepository() { 
    //Get "T" and assign it to this.entityClass 
    Type genericSuperClass = getClass().getGenericSuperclass(); 

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

    entityClass = (Class<T>) parametrizedType.getActualTypeArguments()[0]; 
} 
Cuestiones relacionadas