13

私は長い間この問題に悩まされています。私はしばらくの間この問題を検索しましたが、解決策はどれも機能しませんでした。

構造:

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

私も私ので使用し<context:component-scan>ています。application-config.xml + <tx:annotation-driven />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
4

2 に答える 2

16

@Repositoryから注釈を削除しAbstractGenericDAOて作成しますabstract:

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

問題が発生する@Repositoryのは の特殊化です@Component。つまり、Spring はAbstractGenericDAOインジェクション用のインスタンスを作成しようとします。AbstractGenericDAOスーパークラス ( ) はジェネリックではないため、そのをObjectにダウンキャストすることはできません。そのため、このコード行は失敗します ( を使用して手動でインスタンス化しようとした場合と同じように)。TypeParameterizedTypenew AbstractGenericDAO()

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

特殊化されたクラスShlkActiveWorkflowDAOImplには、引き続き注釈を付ける必要があります@Repository。Spring がこのクラスのインスタンスを作成しようとすると、AbstractGenericDAOコンストラクターへの暗黙的な呼び出しが発生しますが、今回は上記のコード行が期待どおりに実行されます。これは、ジェネリックのサブクラスであるgetClass()リターンが原因で発生します(したがって、ダウンキャストが機能します)。ShlkActiveWorkflowDAOImpl.classAbstractGenericDAOParameterizedType

ShlkActiveWorkflowDAOImpl extends AbstractGenericDAO<ShlkActiveWorkflow, Serializable>実際の型ShlkActiveWorkflowは実行時に正しく反映されるためです。これは、コンストラクター Class<T>への参照の受け渡しを回避するための既知の回避策です。AbstractGenericDAO

@Autowiredの注釈が心配な場合でも、気AbstractGenericDAOにしないでください。サブクラスの 1 つのインスタンスを注入すると、Spring はすべてを正しく接続します。

于 2012-06-17T00:33:55.743 に答える
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];
于 2015-01-29T08:43:04.187 に答える