복붙노트

[SPRING] 추상 DAO 패턴과 Spring의 "프록시를 캐스팅 할 수 없습니다 ..."라는 문제!

SPRING

추상 DAO 패턴과 Spring의 "프록시를 캐스팅 할 수 없습니다 ..."라는 문제!

나는 이것이 매우 자주 묻는 것을 안다. 그러나 나는 일하는 해결책을 찾을 수 없다 :

이것은 내 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
}

그리고 이것은 하나의 개체의 DAO입니다.

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 메소드를 정의합니다.

Interface PersonDao는 Addon 메소드없이 AbstractDAO를 확장합니다.

AbstractDao의 JPA 구현을 정의한 AbstractDaoJpaImpl 클래스

PersonDaoImpl 클래스는 AbstractDaoJpaImpl을 확장하고 PersonDao 및 OtherInterface를 구현하며 aditionalMethods ()를 추가합니다.

IF, PersonDaoImpl은 PersonDao 만 구현하며, OtherInterface.additionalMethods ()를 구현하지 않으면 모든 것이 정상적으로 작동합니다.

나는 사용할 수있다.

<tx:annotation-driven transaction-manager="transactionManager" /> 

내 봄 XML 파일에

그러나 PersonDaoImpl은 OtherInterface를 구현합니다. 테스트 / 실행 중 PersonDao에서 PersonDaoImpl 또는 OtherInterfaces로 DAO를 캐스팅해야합니다.

@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를 PersonDaoImpl로 캐스트 할 수 없습니다"예외를 throw 할 때 발생합니다.

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

이것은 종종 googleing 때, 에 proxy-target-class = "true"를 추가 할 것을 제안합니다.

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"  />

이렇게하면 JDK의 동적 프록시 대신 CGLIB가 사용됩니다.

하지만 스프링을 초기화 할 때 또 다른 예외가 발생합니다.

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,

해결법

  1. ==============================

    1.당신은 잘못된 문제를 해결하고 있습니다. 프록시 된 콩은 원래 클래스에 캐스트 될 수있는 방법이 아닙니다. 그것은 의존성 주입의 모든 부분을 망칠 것입니다. 결국 : 인터페이스로 종속성을 지정할 때 계약을 수행하지만 구현 세부 사항은 충족시키지 않는 bean을 요청하고 있습니다. 원래 빈 클래스로 변환하면이 느슨한 연결이 끊어집니다.

    당신은 잘못된 문제를 해결하고 있습니다. 프록시 된 콩은 원래 클래스에 캐스트 될 수있는 방법이 아닙니다. 그것은 의존성 주입의 모든 부분을 망칠 것입니다. 결국 : 인터페이스로 종속성을 지정할 때 계약을 수행하지만 구현 세부 사항은 충족시키지 않는 bean을 요청하고 있습니다. 원래 빈 클래스로 변환하면이 느슨한 연결이 끊어집니다.

    당신은 추가 메서드가 당신이 OtherInterface라고 부르는 인터페이스에 의해 백업된다는 것을 말하고 있습니다, 그래서 대신 그것을 사용하지 마십시오. 결국 프록시는 삽입 된 클래스뿐만 아니라 모든 대상 클래스의 인터페이스를 구현합니다.

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

    기본적으로 다음 옵션을 사용할 수 있습니다 (깨끗한 상태에서 더러운 상태로 정렬).

  2. ==============================

    2.예 스프링은 항상 프록시 클래스를 생성하고 XML 구성에 의한 비 관입 식 짜기와 a핑을 실제로 발견 한 방법을 알려줍니다 ... 그 오류에 대한 인터넷 검색을 봄 문서에서 수행하십시오.

    예 스프링은 항상 프록시 클래스를 생성하고 XML 구성에 의한 비 관입 식 짜기와 a핑을 실제로 발견 한 방법을 알려줍니다 ... 그 오류에 대한 인터넷 검색을 봄 문서에서 수행하십시오.

  3. from https://stackoverflow.com/questions/3852564/abstract-dao-pattern-and-springs-proxy-cannot-be-cast-to-problem by cc-by-sa and MIT license