7/8, 7/9 AOP 프로그래밍

박세현·2024년 7월 8일

Spring

목록 보기
2/15
post-thumbnail

AOP 프로그래밍

  • Aspect Oriented Programming : 관점 지향 프로그래밍
    • 관점 : 개발자의 공통적인 관심사항 = 공통기능

  • 공통 기능, 핵심기능 분리 기술
    • 공통 기능 - 스프링이 대신 수행
    • 핵심 기능 - 개발자 정의

의존성

  • spring-aop API (API라 구현체 필요 -> aspectjweaver)
    • implementation 'org.springframework:spring-context:6.1.10'
  • aspectjweaver (구현체)
    • implementation 'org.aspectj:aspectjweaver:1.9.22.1'

참고) 스프링이 제공하는 모든 관리 기능의 전제조건

  • 스프링이 관리하는 객체만 관리 기능을 제공한다.
    = 스프링 컨테이너에 있는 객체만 적용 가능하다.


1. 스프링의 프록시(proxy)

  • 데코레이터 패턴 = 스프링의 프록시(proxy)
    • 디자인 패턴의 프록시와는 다르다 -> 통제가 들어가면 디자인 패턴의 프록시
    • 스프링에선 대신해준다의 의미에서 프록시
  • 공통기능은 대신 수행해주고 핵심기능은 내가 해야함

참고) 팩토리얼 연산
ex) !5 = 5 * 4 * 3 * 2 * 1

  • 일반 반복문 -> 예시1)
  • 재귀 방식 : 구조는 간단 벗 성능은 떨어짐 -> 예시2)
  • 예시1), 예시2) 방식은 다르지만 연산결과는 같다


예시1) 팩토리얼 연산_일반 반복문



예시2) 팩토리얼 연산_재귀방식(함수에 함수를 호출)



예시3) 팩토리얼 연산 성능 차이 비교하기



예시) 핵심기능, 공통기능 구분

ㄴ 팩토리얼 연산 : 핵심기능(없어선 안됨)
ㄴ 성능차이 구분 : 공통기능(없어도 되고 있으면 좋고)
ㄴ 공통기능과 핵심기능을 분리해서 효율적으로 구성하는것이 데코레이터 패턴(프록시)



예시1) 스프링의 프록시

ㄴ 핵심기능을 대신 수행

ㄴ 직접 계산기 기능을 수행하지만 않지만 다른 객체의 힘을 빌려 대신 핵심기능을 수행



예시2) 데코레이터 패턴=스프링의 프록시=대신 수행



예시) 데코레이터 패턴



1) 스프링의 동적 프록시(proxy)

  • java.lang.reflect.Proxy
    • InvocationHandler(항상 여기로 유입되어 핵심기능을 invoke()가 대신 수행한다)
  • 인터페이스를 통한 프록시
  • 인터페이스 정의가 필수 = 인터페이스가 없으면 동적 프록시 생성❌

참고)
직접 동적 프록시를 만들 일은 없지만 이해하기 위해서 하는거


예시)

ㄴ 대신 수행



예시) 스프링의 프록시(프록시컬큐레이터, 정적프록시)와 비교하면서 보기(컬큐레이터 핸들러, 동적프록시)

Object result = method.invoke(obj, args);
ㄴ 대신 수행하는 역할



예시) 동적 프록시 만들기

ㄴ 인터페이스 + 추상메서드 정의

ㄴ 재귀함수 정의

ㄴ InvocationHandler(핵심기능 대신 수행)
ㄴ 전부다 여기로 유입되고 여기서 호출 됨

ㄴ 매개변수 쳌

ㄴ 유입! 이 출력됨 = 바로 호출되는것이 아니라 invoke()를 거쳐서 호출된다는 의미

ㄴ 무조건 여기를 거쳐가기 때문에 앞뒤로 추가기능을 정의하면 추가기능도 같이 실행됨 = 공통기능 정의하자

ㄴ 공통기능 정의함
ㄴ 동적 프록시 : 핵심기능을 대신 수행 -> 범용적이기 때문에 모든 클래스, 인터페이스에 적용 가능하다

ㄴ 원래 메서드인 factorial()에 정의하지 않아도 공통기능이 실행됨




2. AOP

1) @Aspect

  • 공통기능이 정의된 클래스
  • 공통기능이 정의된 클래스 위에는 @Aspect 붙이기
  • AOP로 공통기능을 정의할 클래스이다


2) @Pointcut

  • 공통기능이 적용될 패키지 범위를 Ant 패턴을 통해 지정함
  • execution 명시자
  • Ant 패턴으로 적용될 범위를 설정 할 수 있음
  • 공통기능이 적용될 패키지 범위, 메서드 패턴


① Ant 패턴

  • . -> exam01. -> exam01 패키지의 하위 클래스
  • .. -> exam01.. -> exam01 패키지를 포함한 하위 패키지 포함 모든 클래스
    ex)

ㄴ 매개변수가 0개 이상 = 모든 메서드

* = 모든 자료형을 의미?
* 1개 = 매개변수 1개?


*,* 매개변수가 2개짜리 메서드



3) 공통 기능을 수행할 메서드 위에

  • @Around : 가장 많이 사용
    메서드 호출 전, 호출 후 공통 기능

  • @Before
    메서드가 호출되기 전 공통 기능

  • @After
    메서드가 호출 된 후 공통 기능

  • @AfterReturing
    반환값을 내보낸 후 공통 기능
    예외가 발생하면 실행이 안됨

  • @AfterThrowing
    예외가 발생한 후 공통 기능

  • ProceedingJoinPoint
    • Object proceed() : 핵심 기능 대신 실행
    • Signature getSignature() : 호출한 메서드 정보
      • getTarget() : 실제 메서드를 호출한 객체(RecCalculator...)
      • Object[] getArgs() : 인수 목록
  • Signature
    • String getName()
    • String toLongString()
    • String toShortString()

예시)

ㄴ 핵심기능

ㄴ 스프링 컨테이너 안에 관리객체 수동으로 등록함
(몇개 안되서 걍 이렇게함ㅇㅇ)

ㄴ 컨테이너에 관리객체 수동등록함 = 관리객체여야지만 프록시 사용 가능
ㄴ @EnableAspectJAutoProxy : AOP 자동 설정 애노테이션

ㄴ 유입이 출력됨
= process()메서드를 거쳐서 factorial()가 실행이 되었다



예시) Signature



예시) @Before, @After

ㄴ 2번을 기준으로 시점 보기
ㄴ 1 -> 2 -> 3 순으로 호출됨
ㄴ 왜 출력은 이 순서지...



예시) @AfterReturing

ㄴ 특이한점 : Object returnValue - 반환값도 넘어온다



예시) @AfterThrowing

예시)

ㄴ RecCalculator로 하면 오류 뜸(노 서치빈 데피니션)
ㄴ RecCalculator객체를 바로 가져올 수 없음
ㄴ 왜? 프록시를 적용했기 때문
ㄴ 자바의 표준적인 프록시는 인터페이스 기반으로 만들어짐
ㄴ 프록시로 객체를 생성해서 RecCalculator에는 객체가 없다...?
= 스프링 컨테이너안에 프록시 객체는 있지만 RecCalculator객체는 없다

ㄴ 등록된 빈은 프록시만 있다

ㄴ 등록된 빈은 프록시만 있다

ㄴ 병렬적인 구조
ㄴ 프록시와 RecCalculator는 서로 상관없는 클래스

ㄴ 자바에선 인터페이슨 기반 프록시가 기본이지만 이걸 이용하면 클래스기반 프록시가 될 수 있다
ㄴ true로 바꾸면 아래처럼 상속받는 구조로 프록시 사용 가능

ㄴ 서브클래스 기반 프록시(다형성) -> 설정만 바구면 이렇게 가능하다
ㄴ 표준적인건 아님

ㄴ 서브클래스 기반 프록시(다형성)

ㄴ 이제 오류 안뜸




3. @Order

  • 프록시의 적용 순서, 숫자가 작은 순서 부터 적용

예시) 캐시 만들기_@Order 사용하는 이유

ㄴ 프록시가 2개가 사용되고 있다...?

ㄴ 항상 캐시가 먼저 저장이되고 그다음에 시간 프록시(계산기)가 실행되어야 함
-> 순서를 어떻게 정하지?
-> @Order 사용



예시) @Order 사용




4. 프록시 생성방식




5. @Around의 Pointcut 설정과 @Pointcut 재사용

예시) 포인트컷 사용하지 않고도 사용 가능



예시) 많이쓸때는 따로 빼서도 사용 가능

profile
귤귤

0개의 댓글