book_note/토비의 스프링

토비의 스프링 VOL.1 CH6(2)

jjoylee 2021. 7. 10. 17:02

ProxyFactoryBean

  • 프록시를 생성해서 빈 오브젝트로 등록하게 해주는 팩토리 빈
  • 순수하게 프록시를 생성하는 작업만을 담당
  • 부가기능은 MethodInterceptor 인터페이스를 구현해서 만든다. (타깃 오브젝트에 대한 정보도 제공받는다.)
  • 새로운 부가기능을 추가할 때마다 프록시와 프록시 팩토리 빈을 추가하지 않아도 된다.
  • 독립적이고, 여러 프록시가 공유할 수 있는 어드바이스와 포인트컷으로 확장 기능을 분리할 수 있다.
@Test
public void proxyFactoryBean(){
    // 인터페이스 타입 전달할 필요 없음.
    ProxyFactoryBean pfBean = new ProxyFactoryBean();
    pfBean.setTarget(new HelloTarget());
    pfBean.addAdvice(new UppercaseAdvice()); // 여러개의 MethodInterceptor 추가 가능
}

Advice

  • 타깃 오브젝트에 적용하는 부가기능을 담은 오브젝트 (부가기능 제공)
  • InvocationHandler와 다르게 타깃과 메소드 선정 알고리즘 코드에 의존하지 않는다.
  • 직접 타깃을 호출하지 않는다.
  • 부가기능 재사용 가능
  • Advice : 템플릿, MethodInvocation : 콜백

// 타깃 오브젝트에 종속 x
public class UppercaseAdvice implements MethodInterceptor {
    @Override
    // MethodInvocation는 타킷 오브젝트의 메소드를 실행할 수 있다. 타깃 오브젝트의 정보를 가지고 있다.-
    public Object invoke(MethodInvocation invocation) throws Throwable {
        String ret = (String)invocation.proceed(); // 타킷 메소드 호출 (콜백 오브젝트)
        return ret.toUpperCase();
    }
}

Pointcut

  • 메소드 선정 알고리즘을 담은 오브젝트
  • 클라이언트 -> 프록시 메소드 호출 -> 포인트 컷에서 부가기능 부여할 메소드인지 체크 -> 어드바이스 호출
  • 어드바이저 : 포인트컷 + 어드바이스
    NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
    pointcut.setMappedName("sayH*"); // sayH로 시작하는 메소드에만 부가기능 적용
    pfBean.addAdvisor(new DefaultPointcutAdvisor(pointcut, new UppercaseAdvice()));

BeanPostProcessor

  • 스프링 빈 오브젝트로 만들어지고 난 후에, 빈 오브젝트를 다시 가공할 수 있다.
  • DefaultAdvisorAutoProxyCreator 등록되어 있을 경우 : 빈 생성 -> 빈 후 처리기 -> 어드바이저 포인트 컷 정보를 확인해 프록시 적용 대상인지 확인 (클래스 확인 후 메소드 확인) -> 적용 대상이면 프록시 생성기에 프록시를 만들게 함 -> 프록시에 어드바이저 연결 -> 실제 빈 대신 프록시 빈 전달
  • 직접 타겟과 어드바이저를 설정해주지 않아도 된다.
    <!-- 빈 후처리기 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

    <!-- 클래스 이름이 ServiceImpl로 끝나면 프록시 적용 -->
    <bean id="transactionPointcut" class="toby.spring.study.service.NameMatchClassMethodPointcut">
        <property name="mappedClassName" value="*ServiceImpl"/>
        <property name="mappedName" value="upgrade*"/>
    </bean>

    <!-- 만들어진 프록시의 upgrade로 시작하는 메소드에 transactionAdvice 연결 -->
    <bean id="transactionAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
        <property name="advice" ref="transactionAdvice"/>
        <property name="pointcut" ref="transactionPointcut"/>
    </bean>

    <bean id="transactionAdvice" class="toby.spring.study.service.TransactionAdvice">
        <property name="transactionManager" ref = "transactionManager"/>
    </bean>

포인트컷 표현식

  • 표현식 언어를 사용해서 포인트컷을 작성할 수 있도록 하는 방법
  • 문법구조
    • execution() : 메소드의 시그니처 비교, 클래스 이름에 적용되는 패턴은 타입 패턴이다.
    • execution([접근 제한자 패턴] 리턴 값 타입패턴 [ 패키지 클래스 타입패턴.] 메소드 이름패턴 (파라미터 타입패턴 | "..",...) [throws 예외 패턴])
    • bean() : 빈의 이름으로 비교 (ex. bean(*Service) - 아이디가 Service로 끝나는 모든 빈)
    • annotation() : 애노테이션이 적용되어 있는 것으로 보고 메소드를 선정

AOP

  • 애플리케이션의 핵심적인 기능에서 부가적인 기능을 분리해서 모듈로 만들어 설계하고 개발하는 방법 ( 특정한 관점을 기준으로 바라볼 수 있게 해준다는 의미에서 관점 지향 프로그래밍이라고도 한다. )
  • 프록시 AOP : 어드바이스가 적용되는 객체를 프록시로 만들어서 DI로 연결된 빈 사이에 적용해 타기의 메소드 호출 과정에 참여해서 부가기능을 제공한다.
  • 주요 용어
    • 타깃 : 부가기능을 부여할 대상
    • 어드바이스 : 타깃에게 제공할 부가기능을 담은 모듈
    • 조인 포인트 : 어드바이스가 적용될 수 있는 위치(타깃 오브젝트가 구현한 인터페이스의 모든 메소드)
    • 포인트컷 : 어드바이스를 적용할 조인 포인트를 선별하는 작업 또는 기능을 정의한 모듈
    • 프록시 : 클라이언트와 타깃 사이에서 부가기능을 제공하는 오브젝트
    • 어드바이저 : 포인트컷 + 어드바이스 객체
    • Aspect : AOP의 기본 모듈 (어드바이저는 단순한 Aspect라 볼 수 있다.)

Reference


책 : 토비의 스프링 3.1 Vol.1 스프링의 이해와 원리 (저 이일민)