Spring의 AOP (Aspect Oriented Programming)에서는 두 가지 타입의 Proxy를 지원 한다.
첫번째는 JDK Dynamic Proxy이고 다른 하나는 CGLib 방식의 Proxy 이다.

두 가지 동작 방식에 몇가지 차이점은 있으나 가장 중요한 것은 JDK Proxy는 인터페이스에 대한 Proxy만을 지원한다는 것이다.

이 방식은 추가적인 라이브러리 없이 Proxy를 사용한다는 장점이 있으나, 기존에 작성되었던 코드에 AOP를 적용하려 할때 Interface가 선언되어 있지 않으면 Proxy 자체가 동작하지 않고 아래와 같은 Exception Log 만 남기고 실행되지 않는다.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 

'someController': Autowiring of fields failed; nested exception is

org.springframework.beans.factory.BeanCreationException: Could not autowire 

field:some.package.name.CategoryService some.package.name.categoryService; nested exception

 is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 

'categoryServiceImpl': Autowiring of fields failed; nested exception is

org.springframework.beans.factory.BeanCreationException: Could not autowire field: private 

nsome.package.name.CategoryDao some.package.name.categoryDao; nested exception is

java.lang.IllegalArgumentException: Can not set some.package.name.CategoryDao field 

nsome.package.name.categoryDao to $Proxy15


이 내용을 간과 (망각) 하고 있다가 나중에 Aop 설정/구현 후 위와 같은 에러를 만나면 굉장히 당황 스럽게 된다.

실제 에러로그에 출력된 Exception도 원래 원인이랑은 좀 거리가 있어 보인다.. (게다가 IllegalArguementException 같은 메세지엔 디버깅에 별 도움이 되지도 않는다.)

이 문제는 AOP로 사용하려는 객체를 Interface, implement 로 구분해서 구현 하거나, 아니면 CGLib proxy를 쓰도록 아래처럼 Spring ApplicationContext에 proxy-target-class="true" 라고 선언해 주는 방법이 있다.

<aop:config proxy-target-class="true">

    <aop:aspect ref="selectCategoryModelAspect">

        <aop:around pointcut-ref="categoryDao.selectModel" method="procedingEvent" />

    </aop:aspect>

</aop:config>


단 이 방법을 사용 하려면 CGLIB와 관련된 Jar를 Project Dependency에 추가해 주어야 한다.

<dependency>

    <groupId>cglib</groupId>

    <artifactId>cglib</artifactId>

    <version>2.1_3</version>

    <scope>runtime</scope>

</dependency>


혹시 Spring으로 AOP를 구현하는데 위와 같은 에러를 만나면 이 부분을 한번 의심해 보는 것이 좋을 것 같다.