2015-02-09 84 views
0

我正在使用Spring 3.2.11.RELEASE。我有类似下面的类...添加@Transactional导致“java.lang.ClassCastException - > java.lang.Class不能转换为java.lang.reflect.ParameterizedType”异常

@Repository("AssessmentImageDao") 
@Transactional 
public class MyObjectDao extends GenericDAO<MyObject> 
{ 

其中超类有

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

然而,这会导致下面的异常...

[ERROR]: org.springframework.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframewor[email protected]62b9a65b] to prepare test instance [[email protected]] 
java.lang.IllegalStateException: Failed to load ApplicationContext 
    at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:99) 
    at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:122) 
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109) 
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75) 
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:284) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) 
    at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:264) 
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) 
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:124) 
    at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:200) 
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:153) 
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) 
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'MyObjectDao' defined in file [/Users/davea/Dropbox/workspace/core/target/classes/org/mainco/subco/myproject/dao/MyObjectDao.class]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class org.mainco.subco.myproject.dao.MyObjectDao]: Common causes of this problem include using a final class or a non-visible class; nested exception is org.springframework.cglib.core.CodeGenerationException: java.lang.ClassCastException-->java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:529) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:191) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:636) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:934) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479) 
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:120) 
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60) 
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:102) 
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:246) 
    at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContextInternal(CacheAwareContextLoaderDelegate.java:64) 
    at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:91) 
    ... 25 more 

有什么重写构造函数以避免这种异常的方法,或者做一些其他的全局配置来解决这个问题?我正在尝试重新编制GenericDao类的每个子类。

+0

您是否使用'org.springframework.transaction.annotation.Transactional'而不是'javax.transaction.Transactional'? – gerrytan 2015-02-09 21:48:37

+0

好的区别,是的,我正在使用org.springframework.transaction.annotation.Transactional。 – 2015-02-11 21:49:02

回答

2

问题是@Transactional注释是通过向类层次结构添加另一个层来实现的 - 这是一个代理类,它扩展了MyObjectDao以实现事务行为。对于此代理类的对象,this.getClass()是代理类,它的getGenericSuperclass()是MyObjectDao本身,而不是参数化类型GenericDAO<MyObject>

您可以稍微更改一下逻辑,以便继续查找getGenericSuperclass链,直到找到ParameterizedType - 如果父母是Class,则尝试祖父母,等等。

或者,查看是否可以推迟超类查找,直到第一次实际需要时(当调用其中一个GenericDAO方法时)而不是在构造函数中进行查找。虽然生成的代理类扩展了MyObjectDao,但它实际上从未实际调用this上的任何超类方法。代理拦截所有方法调用,执行事务逻辑,然后将业务逻辑委托给作为MyObjectDao实例的单独目标对象,而不是子类。

0

您也可以使用多态性并在GenericDAO中创建public abstract Class<? extends MyObject> getHandledType()方法,并使每个实现自我介绍。

或使用Spring Data。

+0

你能否提供一个如何工作的编码例子? – 2015-02-10 22:07:21

+0

@DaveA它需要“重新编码GenericDao类的每个子类”来添加一个新的方法... – 2015-02-12 11:53:15

相关问题