6.4 스프링의 프록시 팩토리 빈

스프링은 일관된 방법으로 프록시를 만들 수 있게 도와주는 추상 레이어를 제공한다
생성된 프록시는 스프링 빈으로 등록되어야 하며, 스프링은 프록시 객체를 생성해주는 기술을 추상화한 팩토리빈 ProxyFactoryBean을 제공해준다

1. 프록시에서 사용할 부가 기능

  • MethodInterceptor 인터페이스를 구현해서 만든다
  • `MethodInterceptorinvoke()ProxyFactoryBean으로부터 타깃 객체에 대한 정보를 함께 제공받기 떄문에, 타깃 객체에 상관없이 독립적으로 생성되어질 수 있다
  • MethodInterceptor 객체는 타깃이 다른 여러 프록시에서 함께 사용할 수 있고, 싱글톤 빈으로 등록 가능하다

2. 어드바이스: 타깃 객체에 종속되지 않는 순수한 부가 기능을 담은 객체

  • MethodInvocation의 동작
    • MethodInvocation은 일종의 콜백 객체로, proceed()를 실행하면 타깃 객체의 메소드를 내부적으로 실행해주는 기능을 가지고 있다.
    • MethodInvocation 구현 클래스는 일종의 공유 가능한 템플릿처럼 동작한다.
    • 앞서 말한 MethodInvocation의 동작 때문에MethodInterceptor는 부가 기능을 제공하는 데만 집중할 수 있다.
  • 여러 개의 부가 기능 제공
    • ProxyFactoryBeanMethodInterceptor 설정 시, addAdvice()를 사용해서 여러 MethodInterceptor를 동시에 추가할 수 있다.
    • 즉, ProxyFactoryBean 하나로 여러 부가 기능을 제공하는 프록시를 생성할 수 있다.
  • 참고: MethodInterceptorAdvice 인터페이스를 상속하고 있는 서브 페이스

3. 포인트컷: 부가기능 적용 대상 메소드 선정 방법

4. 프록시 동작

  1. 프록시가 클라이언트로부터 요청을 받는다.
  2. 포인트컷에 부가 기능을 부여할 메서드인지를 확인해달라고 요청한다.
  3. MethodInterceptor 타입의 어드바이스를 호출한다.

5. 사용된 디자인 패턴

전략 패턴 구조

  • 프록시로부터 어드바이스와 포인트컷을 독립시키고 DI를 사용하게 한 덕분에,
    1. 여러 프록시가 공유해서 사용할 수 있고,
    2. 구체적인 부가 기능 방식이나 메서드 선정 알고리즘이 바뀌면 구현 클래스만 변경해서 설정에 넣어주면 된다

템플릿/콜백 구조

  • 재사용 가능한 기능을 만들어두고 변경되는 부분(콜백 객체와 메서드 호출정보)만 외부에서 주입해서 작업 흐름(부가기능 부여) 중에 사용하는 구조
    • 어드바이스: 일종의 템플릿
    • 타깃을 호출하는 기능을 가지고 있는 MethodInvocation 객체: 콜백

6. 어드바이저: 어드바이스와 포인트 컷을 묶은 조합

7. ProxyFactoryBean 적용

  • MethodInterceptor라는 Advice 서브 인터페이스를 구현한 TransactionAdvice 작성
  • MethodInvocation 타입의 콜백을 이용해서 번거로운 타깃 메서드 호출 작업을 대부분 제거
  • 타깃 메서드가 던지는 예외 또한 InvocationTargetException으로 래핑되지 않고 그대로 캐치해서 처리
public class TransactionAdvice implements MethodInterceptors{	// 스프링의 인터페이스 구현

// 중략


// 타깃을 호출하는 기능을 가진 콜백 객체(MehotdInvocation 타입의 객체)를 프록시로부터 받음
public Object invoke(MehotdInvocation invocation)throws Throwable{

// 중략
  try{
  	Object ret = invocation.proceed(); // 콜백을 호출해서 타깃 메서드 실행 가능
  } catch (RuntimeException e){	// 예외가 래핑되지 않고 타깃에서 보낸 그대로 전달된다

// 생략

6.5 스프링AOP

1. 자동 프록시 생성기

  • 스프링은 컨테이너로서 제공하는 기능 중 많은 부분을 확장할 수 있도록 확장 포인트를 제공해준다.
  • DefaultAdvisorAutoProxyCreator는 어드바이저를 이용한 자동 프록시 생성기로, 스프링은 빈 후처리기가 빈으로 등록되어 있으면 빈 객체가 생성될 때마다 빈 후처리기에 보내서 후처리 작업을 요청한다.

빈 후처리기를 이용한 자동 프록시 생성 방법

  1. DefaultAdvisorAutoProxyCreator 빈 후처리기가 등록되어 있으면, 스프링은 빈 객체 생성마다 후 처리기에 빈을 보낸다.
  2. DefaultAdvisorAutoProxyCreator는 포인트컷을 이용해 전달받은 빈이 프록시 적용 대상인지를 확인한다.
  3. 프록시 적용 대상일 경우,
    1) 내장되 프록시 생성기에게 현재 빈에 대한 프록시를 생성하게 한다.
    2) 만들어진 프록시에 어드바이저를 연결해준다.
    3) 프록시가 생성되면 원래 컨테이너가 전달해준 빈 객체 대신 프록시 객체를 컨테이너에게 돌려준다.
  4. 컨테이너는 최종적으로 빈 후처리기가 돌려준 객체를 빈으로 등록하고 사용한다.

2. 포인트컷의 두 가지 기능

  • 포인트컷은 ClassFilterMethodMatcher 두 가지를 돌려주는 메서드를 가지고 있다
  • 만약 포인트컷 선정 기능을 모두 적용한다면 아래와 같은 순서로 동작하게 된다.
    1. 프록시를 적용할 클래스인지 판단
    2. 적용 대상 클래스 인 경우, 어드바이스를 적용할 메소드인지를 확인
  • ProxyFactoryBean에서는 굳이 클래스 레벨의 필터는 필요 없었지만, DefaultAdvisorAutoProxyCreator는 클래스와 메서드 선정 알고리즘을 모두 갖고 있는 포인트컷과 어드바이스가 결합되어 있는 어드바이저가 필요하다.

클래스 필터가 포함된 포인트컷

public class NameMatchClassMethodPointcut extends NameMatchMethodPointcut{
	public void setMappedClassName(String mappedClassName){
    	this.setClassFilger(new SimpleClassFilter(mappedClassName));
        // 모든 클래스를 다 허용하던 디폴트 클래스 필터를 
        // 프로퍼티로 받은 클래스 이름을 이용해서 필터를 만들어 덮어씌움

		// 생략

포인트컷 표현식

  • 포인트컷 표현식: 스프링이 제공하는 간단하고 효과적인 포인트컷의 클래스/메서드 선정 알고리즘 작성 방법
  • 스프링이 사용하는 포인트컷 표현식은AspectJ 프레임 워크의 일부 문법을 확장한 표현식으로, AspectJExpressionPointcut 클래스를 사용해서 적용 가능하다.

AspectJ 포인트컷 표현식

  • 포인트컷 지시자를 이용해서 작성하며, 가장 대표적으로 사용되는 지시자는 execution()
execution([접근제한자 패턴] 타입패턴 [타입패턴.]이름패턴 (타입패턴 | "..", ...)[throws 예외패턴])
구성 요소설명예시
접근제한자 패턴public, private 등public
타입패턴반환 타입 (와일드카드 * 가능)*, String, void
타입패턴.메서드가 속한 클래스의 경로com.example.service.*.
이름패턴메서드 이름 (와일드카드 가능)get*, *Service, save
(타입패턴, ...)매개변수 타입 (0개 이상)(int, String), (..)
throws 예외패턴던질 수 있는 예외 타입throws IOException

포인트컷 표현식 문법

  • AspectJ 포인트컷 표현식은 포인트컷 지시자를 이용해 작서 l

0개의 댓글