[Code-State] SECTION-2 Spring AOP 심화

유형찬·2022년 10월 18일
0

Code States

목록 보기
14/21

Spring AOP의 원리 CGlib vs Dynamic Proxy

1. Spring AOP의 원리

Spring AOP는 프록시 패턴을 이용하여 AOP를 구현한다.

프록시 패턴은 클라이언트가 실제 서비스 객체에 접근하는 것이 아니라 프록시 객체를 통해 접근하는 것이다.

프록시 객체는 실제 서비스 객체에 접근하는 역할을 하며, 클라이언트는 프록시 객체를 통해 서비스 객체에 접근한다.

프록시 객체는 클라이언트가 서비스 객체에 접근하기 전에 추가적인 기능을 수행할 수 있다.

이러한 프록시 객체를 프록시 패턴이라고 한다.

특정한 인터페이스를 노출 시키고 싶지 않고 , 외부로 부터 감추고 싶을 때 사용한다.

디자인 패턴의 Proxy와 Spring AOP의 Proxy

Spring AOP의 프록시는 디자인 패턴의 프록시와는 다르다.

Spring AOP의 프록시는 프록시 객체가 실제 서비스 객체를 상속받아 구현한다.

따라서 프록시 객체는 실제 서비스 객체의 메소드를 호출할 수 있다.

이러한 특징 때문에 Spring AOP의 프록시는 디자인 패턴의 프록시보다 더 많은 기능을 수행할 수 있다.

Spring AOP의 프록시 구현 방법

관심사의 추출은 다음과 같은 방식으로 수행된다.

Proxy를 이용한 런타임 위빙(Runtime Weaving) 을 통해서 관심사를 추출할 수 있다.

여기서 Runtime Weaving 이란?

Weaving is the process of applying aspects to a target object to create a new, proxied object.
-> Weaving은 target 객체를 새로운 proxied 객체로 적용시키는 과정이다.

그래서 Runtime Weaving은?

  • Runtime시에 이러한 Weaving이 진행되는 방식

Spring AOP의 프록시는 두 가지 방법으로 구현할 수 있다.

  • JDK Dynamic Proxy
  • CGLIB

JDK Dynamic Proxy

JDK Dynamic Proxy는 JDK 1.3부터 지원하는 기능이다.

JDK Dynamic Proxy는 인터페이스를 기반으로 프록시 객체를 생성한다.

이 프록시는 InvocationHandler 인터페이스를 상속 받아 구현한다.

InvocationHandler 인터페이스는 다음과 같이 정의되어 있다.


public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable;
}

InvocationHandler 인터페이스는 다음과 같은 역할을 수행한다.

  • 프록시 객체가 호출되면 InvocationHandler의 invoke() 메소드가 호출된다.
  • invoke() 메소드는 프록시 객체가 호출한 메소드의 정보를 담고 있는 Method 객체와 인자를 전달받는다.
  • invoke() 메소드는 실제 서비스 객체의 메소드를 호출하고, 그 결과를 반환한다.
  • invoke() 메소드는 예외를 발생시킬 수 있다.
  • invoke() 메소드는 반환값을 반환할 수 있다.

JDK Dynamic Proxy는 다음과 같은 단점이 있다.

  • invoke() 메소드를 통해서 proxy 로직이 구현되기 때문에, 해당 메소드 코드에 reflection을 해야한다. (성능 저하)

CGLIB

CGLIB는 Code Generation Library의 약자이다.

CGLIB는 Enhancer 클래스를 이용해서 프록시 객체를 생성한다. (상속)

Enhancer 클래스는 다음과 같이 정의되어 있다.


public class Enhancer {
    public static Object create(Class superclass, Callback callback);
    public static Object create(Class superclass, Class[] interfaces, Callback callback);
}

Enhancer 클래스는 다음과 같은 역할을 수행한다.

  • Enhancer 클래스는 프록시 객체를 생성한다.
  • Enhancer 클래스는 프록시 객체가 호출되면 Callback 객체의 intercept() 메소드를 호출한다.
  • intercept() 메소드는 프록시 객체가 호출한 메소드의 정보를 담고 있는 Method 객체와 인자를 전달받는다.
  • intercept() 메소드는 실제 서비스 객체의 메소드를 호출하고, 그 결과를 반환한다.

CGLIB는 다음과 같은 장점이 있다.

  • JDK Dynamic Proxy와 달리, invoke() 메소드를 통해서 proxy 로직이 구현되지 않기 때문에, 해당 메소드 코드에 reflection을 하지 않는다. (성능 향상)
  • JDK Dynamic Proxy와 달리, 인터페이스를 구현하지 않아도 된다.

정리

위 두 가지 방법은 모두 프록시 패턴을 구현하는 방법이다.

JDK Dynamic Proxy의 invoke() 메소드와 CGLIB의 intercept() 메소드는
@Advice 의 개념과 일치한다.

  • Spring AOP는 Proxy를 기반으로 한 Runtime Weaving 방식이다
  • Spring AOP에서는 JDK Dynamic Proxy 와 CGlib 을 통해 Proxy화 한다
  • JDK Dynamic Proxy는 Reflection을 기반으로 이루어지고
  • CGlib 은 상속을 기반으로 이루어진다
profile
rocoli에요

0개의 댓글