【发布时间】:2011-04-20 15:14:44
【问题描述】:
我知道这个问题经常被问到,但我找不到可行的解决方案:
这是我的 AbstractDAO:
public interface AbstractDao<T>
{
public T get(Serializable id);
//other CRUD operations
}
这是我的 JPA 的实现:
public abstract class AbstractDaoJpaImpl<T> implements AbstractDao<T> , Serializable
{
protected EntityManager em;
protected Class<T> clazz;
@SuppressWarnings("unchecked")
public AbstractDaoJpaImpl()
{
ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
this.clazz = (Class<T>) genericSuperclass.getActualTypeArguments()[0];
}
public abstract void setEntityManager(EntityManager em);
//implementations skipped
}
这是一个实体的道:
public interface PersonDao extends AbstractDao<Person>
{
//empty
}
这是它的实现:
@Repository
public class PersonDaoImpl extends AbstractDaoJpaImpl<Person> implements PersonDao , OtherInterface
{
@PersistenceContext(unitName="company")
@Override
public void setEntityManager(EntityManager em)
{
this.em = em;
}
@Override // implements OtherInterface.additionalMethods()
public additionalMethods()
{
// implements...
}
}
整个架构很简单:
接口AbstractDao定义了简单的CRUD方法。
接口PersonDao扩展了AbstractDAO,没有任何插件方法。
类 AbstractDaoJpaImpl 定义了 JPA 的 AbstractDao 实现
class PersonDaoImpl 扩展了 AbstractDaoJpaImpl 并实现了 PersonDao AND OtherInterface ,它添加了附加方法()...
如果,PersonDaoImpl 只实现了 PersonDao ,没有实现 OtherInterface.additionalMethods() ,一切正常。
我可以使用
<tx:annotation-driven transaction-manager="transactionManager" />
在我的 spring 的 XML 文件中。
但是,PersonDaoImpl 实现了 OtherInterface(s) ,在测试/运行时,我必须将 DAO 从 PersonDao 转换为 PersonDaoImpl 或 OtherInterfaces,例如:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:app.xml"})
@TransactionConfiguration(transactionManager="transactionManager" , defaultRollback=false)
public class PersonDaoTest
{
@Inject
PersonDao dao;
@Test
public void testAdditionalMethod()
{
PersonDaoImpl impl = (PersonDaoImpl) dao;
System.out.println(impl.additionalMethod(...));
}
}
问题发生在(PersonDaoImpl) dao 时,抛出“Proxy cannot be cast to PersonDaoImpl”异常:
java.lang.ClassCastException: $Proxy36 cannot be cast to foobar.PersonDaoImpl
at foobar.PersonDaoTest.testAdditionalMethod(PersonDaoTest.java:36)
这个是googleing的时候经常问的,大家建议在<tx:annotation-driven>后面加proxy-target-class="true":
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
这将使用 CGLIB 而不是 JDK 的动态代理。
但是在初始化 Spring 时它会引发另一个异常:
Caused by: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
在 AbstractDaoJpaImpl 的构造函数中:
ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
每个问题都到此为止,我现在找不到任何有效的解决方案。
谁能给我一个可行的解决方案? 非常感谢!
环境:Spring-3.0.4、javaee-api-6.0、javax.inject、cglib-2.2、hibernate-jpa-2.0-api-1.0.0、
【问题讨论】:
标签: java spring cglib genericdao