토비 스프링 AOP (2)

스프링 AOP

자동 프록시 생성

한 번에 여러 개의 빈에 프록시를 적용할 만한 방법이 필요하다

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

토비님 자료

image

영한님 자료

image

BeanPostProcessor 인터페이스를 구현해서 만든 빈 후처리기 !

이것을 이용하면 Bean을 프록시로 바꿔칠 수 있다!

public class BeanPostProcessorTest {

    // Bean Post Processor
    @Slf4j
    static class AToBPostProcessor implements BeanPostProcessor {
        
        @Override
        public Object postProcessAfterInitialization(Object bean, String
                beanName) throws BeansException {
            log.info("beanName={} bean={}", beanName, bean);
            if (bean instanceof A) {
                return new B();
            }
            return bean;
        }
    }

    // Configuration
    @Slf4j
    @Configuration
    static class BeanPostProcessorConfig {

        @Bean(name = "beanA")
        public A a() {
            return new A();
        }

        @Bean
        public AToBPostProcessor helloPostProcessor() {
            return new AToBPostProcessor();
        }
    }

    @Slf4j
    static class A {
        public void helloA() {
            log.info("hello A");
        }
    }

    @Slf4j
    static class B {
        public void helloB() {
            log.info("hello B");
        }
    }
    
    @Test
    void postProcessor() {
        ApplicationContext applicationContext = new
                AnnotationConfigApplicationContext(BeanPostProcessorConfig.class);
        //beanA 이름으로 B 객체가 빈으로 등록된다.
        B b = applicationContext.getBean("beanA", B.class);
        b.helloB();
        //A는 빈으로 등록되지 않는다. Assertions.assertThrows(NoSuchBeanDefinitionException.class,
        () -> applicationContext.getBean(A.class));
    }
}

확장된 포인트컷

public interface Pointcut {
    ClassFilter getClassFilter();
    MethodMatcher getMethodMatcher();
}

프록시를 적용할 클래스인지 판단하고 나서, 적용 대상이라면 부가 기능을 적용할 메서드인지를 판단한다

포인트컷 표현식

AspectJExpressionPointcut에서 제공하는 포인트컷 표현식을 사용하면 복잡한 선정 조건을 쉽게 지정할 수 있다.

포인트컷 표현식 문법

포인트컷 지시자 중에서 가장 많이 사용되는 것은 execution() 이다

execution([접근제한자] 반환타입 [패키지+클래스.]메서드이름 (파라미터))
@Test
public test() {
    AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
    pointcut.setExpression("execution(public int wooteco.chess.Pawn.attack(Row, Column))");

    assertThat(pointcut.getClassFilter().matches(Pawn.class)).isTrue();
    assertThat(pointcut.getMathodMatcher().matches(Pawn.class.getMethod("attack", Row.class, Column.class), null)).isTrue();
}

포인트컷 표현식 테스트

execution(int minus(int, int))

반환타입: int
클래스명: anything
메서드명: minus
파라미터: int, int

execution(* minus(int, int))

변한 부분만 작성! 반환타입: anything

execution(* minus(..))

파라미터: anything

execution(* *(..))

메서드명: anything

포인트컷 표현식을 이용하는 포인트컷 적용

@Transactional 이라는 어노테이션만을 아래와 같이 선정할 수 있다

@annotation(org.springframework.transaction.annotation.Transactional)

AOP란 무엇인가

AOP: 관점 지향 프로그래밍

공통 관심사를 분리함으로써 핵심기능을 설계하고 구현할 때 OOP의 가치를 지킬 수 있도록 도와주는 것

[AOP 적용기술]

##

프록시를 이용한 AOP

런타임에 조작

  • 자바의 기술들 대거 조합해서 AOP 지원
    • Spring IoC
    • Dynamic Proxy
    • CGLib
    • Design Pattern (Decorator / Proxy)
    • PointCut
    • Bean Post Processor

핵심은 프록시를 이용했다는 것 !

바이트코드 생성과 조작을 통한 AOP

  • 컴파일 / 클래스 로딩타임에 조작

AspectJ의 AOP 기술.

스프링의 프록시기술처럼 간접적인 방식이 아니라 직접 타깃을 뜯어고치는 방식.

그렇다고 .java파일을 고치는 건 아니고 .class파일을 뜯어고친다

바이트코드를 직접 조작할 경우 스프링 IoC, 자동 프록시 생성의 도움을 받지 않아도 AOP를 적용할 수 있다

둘째는 프록시 방식보다 유연한 AOP가 가능.

  • private 메서드 호출, 스태틱 메서드 호출, 필드 입출력 등

[김영한님] AOP 적용기술

컴파일 시점

  • .java 파일을 .class 파일(바이트코드)로 만들 때 적용
  • 가장 SOLID한 방식이다, 파일에 직접 부가 기능을 넣는 것

image

단점

  • 특별한 컴파일러가 필요하고 복잡하다

클래스 로딩 시점

  • .class 파일을 JVM에 로딩할 때에 적용
  • .class 파일 자체는 온전하나 JVM에 적재될 때 부가 기능을 넣는다

image

단점

  • 로드 타임 위빙은 자바를 실행할 때 특별한 옵션( java -javaagent )을 통해 클래스 로더 조작기를 지정해야 하는데, 이 부분이 번거롭고 운영하기 어렵다.

  • 자바 실행시 java -javaagent을 통해 클래스 로더 조작기를 지정해야하는데, 이 부분이 번거롭다 !

image

(저런 모습이 아닌가 생각한다!)

런타임 시점

  • JVM로딩 된 후에 Spring IoC에 적재될 때 적용
  • 종합아트예술

image

바이트코드 생성과 조작을 통한 AOP

  • AjpectJ: 대표적인 AOP 기술
  • 직접 타깃을 뜯어고쳐서 부가 기능을 넣는 방법을 사용한다
  • 컴파일 된 타깃 .class 파일을 수정하거나 JVM 로딩되는 시점에 가로채서 바이트 코드(.class)를 조작한다

AOP의 용어

  • 타깃
    • 부가기능을 부여할 대상이다. 경우에 따라서 또 다른 부가기능을 담은 프록시 오브젝트일 수도 있다.
  • 어드바이스
    • 타깃에 적용할 부가기능을 담은 모듈(것)
  • 조인포인트
    • 클라이언트가 호출할 수 있는 모든 메서드
    • 포인트컷의 후보가 된다
  • 포인트컷
    • 부가기능을 적용할 클래스와 메서드를 선별하는 모듈

image

출처: https://velog.io/@yeziwoo/%EB%B9%84%EA%B3%B5%EA%B0%9CSpring-Boot-AOPAspect-Oriented-Programming-%EA%B4%80%EC%A0%90-%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D

위빙

  • 아래와 같이 비즈니스 로직을 횡단 관심사를 통해서 연결해주는 것

image

  • 어드바이저
    • 포인트컷 + 어드바이스
  • 애스펙트
    • 어드바이저가 싱글톤 형태로 존재하는 것

[트랜잭션 속성]

트랜잭션 정의

더 이상 쪼갤 수 없는 최소 단위의 작업 (원자성)

TransactionDefinition 인터페이스에는 트랜잭션의 동작방식에 영향을 줄 수 있는 네 가지 속성이 정의되어 있다

  • 전파
  • 격리수준
  • 제한시간
  • 읽기전용

트랜잭션 전파

  • PROPAGATION_REQUIRED
    • 기본설정이다!
    • 없으면 합류하고 있으면 합류하지 않는다
  • PROPAGATION_REQUIRED_NEW
    • 항상 새로운 트랜잭션을 시작한다.
    • 부모 트랜잭션이 있든 없든 상관없이 새로운 트랜잭션을 만들어서 독자적으로 동작한다
  • PROPAGATION_NOT_SUPPORTED
    • 트랜잭션 없이 동작하도록 만들 수 있는 설정
    • 수많은 트랜잭션 경계 설정 중에서 하나만 없이 만들 때

트랜잭션 전파 - 실험

BizService -> InnerService가 있을때

BizService

  • execute();
  • innerExecute();

InnerService

  • execute();

Q. BizService에서

image

위와 같은 상황에서 예외가 터지는가?

(샌드위치식으로 진행할 것)

Q. BizService에서 @T (X) execute -> @T private innerExcute

Tx가 걸리는가? X

Q. 위에서 innerExcute가 public일 경우

X

Q. BizService @T -> InnerService @T

O

아래와 같은 상황에서, 커밋은 어떻게 이루어질 것인가?

image

격리수준

  • 격리수준은 기본적으로 DB에 설정되어 있지만 JDBC 드라이버나 DataSource 등에서 재설정할 수 있다.

제한시간

  • Tx 수행 제한시간을 설정할 수 있다
    • 기본 설정은 제한 시간이 없다

읽기 전용

  • Tx내에서 데이터를 조작하는 시도 막아줄 수 있다

만일 조작을 시도하려 할 시 TransientDataAccessResourceException이 발생한다

  • DB 접근 기술에 따라서 성능이 향상될 수 있다
    • JPA - 스냅샷

TransactionInterceptor

  • 디버거 수행시 TransactionInterceptor.invoke -> TransactionAspectSupport.invokeWithinTransaction 라는 곳으로 이동한다

  • 기본적으로 런타임(언체크) 예외에 대해서만 롤백을 수행한다

  • 체크 예외에 대해서는 롤백 수행을 하지 않는다

    • 일부 체크 예외는 정상 작업 흐름으로 간주해야하는 경우가 있기 때문
    • 사실 이부분은 읽을 때마다 이해가 잘 가지 않는다…

프록시 방식 AOP는 내부 메서드 호출시 적용되지 않는다

  • 주의사항 !!

image

  • 위와 같은 흐름이다

클라이언트에서 호출한 메서드에서만 적용이 된다

트랜잭션 어노테이션

  • 트랜잭션 적용을 선언적으로 사용할 수 있다

포인트컷과 어드바이스

  • TransactionAttributeSourcePointcut
  • TxInterceptor와 AnnotationTransactionAttributeSource




© 2020.12. by 따라쟁이

Powered by philz