의존성
- spring-aop API (API라 구현체 필요 -> aspectjweaver)
- implementation 'org.springframework:spring-context:6.1.10'
- aspectjweaver (구현체)
- implementation 'org.aspectj:aspectjweaver:1.9.22.1'
참고) 스프링이 제공하는 모든 관리 기능의 전제조건
- 스프링이 관리하는 객체만 관리 기능을 제공한다.
= 스프링 컨테이너에 있는 객체만 적용 가능하다.
참고) 팩토리얼 연산
ex)!5 = 5 * 4 * 3 * 2 * 1
- 일반 반복문 -> 예시1)
- 재귀 방식 : 구조는 간단 벗 성능은 떨어짐 -> 예시2)
- 예시1), 예시2) 방식은 다르지만 연산결과는 같다
예시1) 팩토리얼 연산_일반 반복문


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


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

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

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

ㄴ 핵심기능을 대신 수행

ㄴ 직접 계산기 기능을 수행하지만 않지만 다른 객체의 힘을 빌려 대신 핵심기능을 수행
예시2) 데코레이터 패턴=스프링의 프록시=대신 수행



예시) 데코레이터 패턴

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






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


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

예시) 동적 프록시 만들기

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

ㄴ 재귀함수 정의

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

ㄴ 매개변수 쳌


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




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

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

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





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


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

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

@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로 바꾸면 아래처럼 상속받는 구조로 프록시 사용 가능

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

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

ㄴ 이제 오류 안뜸
예시) 캐시 만들기_@Order 사용하는 이유




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

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


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

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


