지금까지 사용중인 객체가 proxy객체 인지 아닌지 구별하기 위해
instanceof 연산자로 SpringProxy 타입을 비교해서 구분 했는데
이미 그렇게 구분해서 값을 돌려주는게 있었네요...

org.springframework.aop,.support.AopUtils
신고

'Spring > AOP' 카테고리의 다른 글

Proxy 객체인지 확인하려면...?  (0) 2009.01.21
Spring AOP - aop스키마 기반  (0) 2008.01.14
Spring AOP - @AspectJ  (0) 2007.12.31
Spring AOP APIs - ProxyFactoryBean, AutoProxy  (0) 2007.12.31
Spring AOP APIs - Advisor  (2) 2007.12.31
Spring AOP APIs - Pointcut  (0) 2007.12.31
Posted by 째코
Spring AOP는 다른 AOP 프레임워크와 달리 런타임시 Target 객체의 Porxy 객체를 생성함으로써 AOP 를 구현합니다. Proxy 객체를 생성할때는 CGLIB 또는 JDK DynamicProxy를 이용하게 되는데 만약 Target 클래스가 인터페이스 기반이라면 JDK DynamicProxy를 이용하게 되고 인터페이스 기반이 아니라면 CGLIB를 이용하게 됩니다. 하지만 인터페이스 기반이라도 CGLIB를 이용하도록 설정 가능 합니다.

ProxyFactoryBean
Proxy 객체를 만들 수 있는 가장 기본적인 클래스는 ProxyFactoryBean 입니다. 다른 FactoryBean들과 마찬가지로 내부에서 생성된 객체를 리턴하며 단지 Proxy된 객체를 리턴한다는 것만 다릅니다.
앞서 나왔던 Advisor를 이용해 Proxy객체를 만들어 보겠습니다.

위 예제에서 ProxyFactoryBean의 target 프로퍼티와 interceptorNames 프로퍼티를 이용해
대상 객체인 Foo와 advice+pointcut의 조합인 advisor를 설정하고 있습니다.
이제 컨테이너로부터 foo를 요청하면 Porxy객체가 리턴 될 것입니다.

ProxyFactoryBean은 설정 가능한 수많은 프로퍼티가 존재합니다.
그 중에서 중요한 것들만 알아 보겠습니다.
target - Proxy의 Target bean
interceptorNames[] - 적용할 Advisor bean
interfaces[] & proxyInterfaces[] - Target 객체에 추가로 구현할 인터페이스
                                                  인터페이스 추가 구현시 반드시 CGLIB 이용해야 함
exposeProxy - Target 객체가 현재 Proxy에 접근 가능한지 여부. Target 클래스 내에서
                      AopContext.currentProxy() 메소드로 현재 Porxy에 접근 가능
proxyTargetClass - CGLIB의 사용 여부. Target 클래스가 인터페이스 기반이라도 이 프로퍼티를 통해
                             CGLIB를 이용할 수 있음

여기서 중요한점이 있습니다.
Target 클래스가 인터페이스를 구현하고 있지 않더라도 interfaces[] & proxyInterfaces[] (이하 interfaces[]) 를 설정하고 proxyTargetClass를 false로 설정할 경우 JDK DynamicProxy(이하 JDK Proxy)를 이용해 Proxy 객체를 만들게 됩니다. 이 때 문제가 발생하는데 Target 객체를 설정한 인터페이스로 다운캐스팅이 불가능 할 뿐만 아니라 인터페이스의 메소드 호출시 추상메소드로 판단하고 예외가 발생 됩니다. 이유는 JDK Proxy가 Proxy객체를 만들 때 Target 클래스가 인터페이스 기반이 아닐경우 intefaces[]에 지정된 인터페이스를 Target 객체 구현하지 못해서 발생하는 문제입니다. 따라서 JDK Proxy가 사용되는 상황이라면 반드시 Target 클래스가 인터페이스 기반이여야 합니다. 만약 위와 같은 상황에서 CGLIB를 이용한다면 Target 클래스에 인터페이스 구현이 제대로 이루어지며 문제는 발생하지 않습니다.
그리고 Target 클래스가 이미 구현하고 있는 인터페이스는 interfaces[] 프로퍼티에 설정할 필요가 없습니다.
이러한 이유로 interfaces에 대한 설명을 "Target 객체에 추가로 구현할 인터페이스" 라고 했습니다.

위 사실들을 토대로 Introdction Advisor를 지정할 경우를 생각해 봅시다.
Introduction Advisor를 interceptorNames[]에 지정 할 경우 Target객체에서 추가 기능이 정의된 인터페이스로 다운캐스팅 하기 위해 interfaces[]에 해당 인터페이스를 지정 할 필요가 없습니다. 왜냐면 Proxy객체 생성 과정중 Advisor가 IntroductionAdvisor일 경우 validateIntroductionAdvisor 메소드에서
IntroductionAdvice가 구현한 인터페이스를 interfaces[] 프로퍼티에 자동으로 등록하기 때문입니다.
이 경우 Target 클래스가 해당 인터페이스를 구현하지 않은 상황이므로 proxyTargetClass 프로퍼티는 true로 설정 해야 합니다.

Global Advisor 사용하기
interceptorNames 프로퍼티의 값으로 와일드 카드를 이용 할 수 있습니다.

AutoProxy

ProxyFactoryBean은 AOP를 적용해야 할 bean이 많을 경우 모든 bean에 대해 설정 하는것은 매우 귀찮은
일 입니다. 다행히 Spring AOP에서는 자동으로 Proxy객체를 생성시켜주는 기능을 가진 bean을 제공 합니다.
아래 두가지 AutoProxy는 ProxyFactoryBean의 속성들이 대부분 존재 합니다.

BeanNameAutoProxyCreator
beanNames[] 에 지정된 bean들에 한해서 interceptorNames[] 로 지정된 advisor가 적용된 Proxy객체를
생성 합니다. beanNames[] 에 와일드카드(*)가 사용 가능한 특징이 있습니다.

DefaultAdvisorAutoProxyCreator
단지 등록만 해두면 advisor들을 찾아서 자동으로 대상을 결정하고 Proxy객체를 생성 합니다.

신고

'Spring > AOP' 카테고리의 다른 글

Spring AOP - aop스키마 기반  (0) 2008.01.14
Spring AOP - @AspectJ  (0) 2007.12.31
Spring AOP APIs - ProxyFactoryBean, AutoProxy  (0) 2007.12.31
Spring AOP APIs - Advisor  (2) 2007.12.31
Spring AOP APIs - Pointcut  (0) 2007.12.31
Spring AOP APIs - Advice  (0) 2007.12.31
Posted by 째코
<aop:scoped-proxy /> 요소는 이전 글(링크) 에서 소개했는데
이번엔 좀 더 자세히 작동 방식에 대해 정리해 보겠습니다.
아래 설정을 보시면 bar가 참조하는 foo의 scope는 session 입니다.

이 설정을 기반으로 한 WebApplicationContext 컨테이너는 foo를 생성할 때
<aop:scoped-proxy /> 요소가 있으므로 foo에 대한 Proxy 객체를 생성 합니다.
Foo(Proxy)객체에 적용된 intercept는 다음과 같습니다.(CGLIB 사용 할 경우)
Cglib2AopProxy$DynamicAdvisedInterceptor
Cglib2AopProxy$DynamicUnadvisedInterceptor
Cglib2AopProxy$SerializableNoOp
Cglib2AopProxy$SerializableNoOp
Cglib2AopProxy$AdvisedDispatcher
Cglib2AopProxy$EqualsInterceptor
Cglib2AopProxy$HashCodeInterceptor

여기서 중요한 것은
DynamicUnadvisedInterceptor 입니다.
DynamicUnadvisedInterceptor 가 적용 되는 메소드는 Object 클래스의 toString(), clone(), finalize() 메소드와 사용자정의 public 메소드(non-static) 입니다.

DynamicUnadvisedInterceptor의 intercept 구현 내용은 크게 2단계로 나뉩니다.
첫번째로 getTarget() 호출 두번째로 원본 메소드 호출이 되겠습니다.
getTarget() 메소드는 최종적으로 AbstractBeanFactory 의 getBean() 메소드를 호출 합니다. 따라서 해당 bean에 정의된 scope가 현재scope(session, request) 에 의해 새로운 객체를 생성하거나 기존의 객체를 돌려 줍니다. 그리고는 돌려 받은 target객체를 통해서 원래 메소드를 호출 합니다.

<lookup-method />는 자신이 직접 Proxy 객체가 되는 반면
<aop:scoped-proxy />는 Proxy 객체를 만들어 주입하는 차이가 있군요
신고

'Spring > Core' 카테고리의 다른 글

LifeCycle 확장  (0) 2007.12.17
LifeCycle  (0) 2007.12.17
<aop:scoped-proxy /> 작동 방식  (5) 2007.12.14
Bean scopes  (0) 2007.12.14
메소드 삽입  (0) 2007.12.14
Autowiring  (0) 2007.12.10
Posted by 째코