gpt4 book ai didi

java - 抽象DAO模式与Spring的 "Proxy cannot be cast to ..."问题!

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:15:42 24 4
gpt4 key购买 nike

我知道这个问题经常被问到,但我找不到可行的解决方案:

这是我的 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...
}
}

整个架构很简单:

接口(interface) AbstractDao 定义了简单的 CRUD 方法。

接口(interface) PersonDao 在没有任何附加方法的情况下扩展了 AbstractDAO。

class AbstractDaoJpaImpl 定义JPA对AbstractDao的实现

class PersonDaoImpl 扩展 AbstractDaoJpaImpl 并实现 PersonDao AND OtherInterface ,它添加了 aditionalMethods()...

如果 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时,抛出“代理无法转换为 PersonDaoImpl”异常:

java.lang.ClassCastException: $Proxy36 cannot be cast to foobar.PersonDaoImpl
at foobar.PersonDaoTest.testAdditionalMethod(PersonDaoTest.java:36)

这个在google的时候经常被问到,大家建议加上proxy-target-class="true"<tx:annotation-driven> :

<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、

最佳答案

您正在解决错误的问题。被代理的 bean 并不意味着以一种或另一种方式转换为原始类。这将打破依赖注入(inject)的全部意义。毕竟:当您将依赖项指定为接口(interface)时,您是在请求一个履行契约的 bean,而不是实现细节。将其强制转换为原始 bean 类会打破这种松耦合。

您是说附加方法由您称为 OtherInterface 的接口(interface)支持,那么为什么不使用它呢?毕竟,代理将实现所有目标类的接口(interface),而不仅仅是注入(inject)的接口(interface)。

@Test
public void testAdditionalMethod()
{
OtherInterface oi = (OtherInterface) dao;
System.out.println(oi.additionalMethod(...));
}

基本上你有这些选项(从干净到脏排序):

  1. 分离您的关注点和使用不同的 bean 不同界面
  2. 创建一个扩展的元接口(interface)OtherInterfacePersonDao 和让你的 bean 实现它元接口(interface)
  3. 将bean 转换到接口(interface)您随时都需要。

关于java - 抽象DAO模式与Spring的 "Proxy cannot be cast to ..."问题!,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3852564/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com