본문은 인프런의 [스프링 핵심 원리 - 고급편]를 수강하고 정리한 글입니다. 필요에 따라 생략/수정된 부분이 있을 수 있으며, 내용이 추후 변경될 수 있습니다.
스프링 핵심 원리 - 고급편
1. 쓰레드 로컬
2. 템플릿 메서드 패턴과 콜백 패턴
3. 프록시 패턴과 데코레이터 패턴
4. 동적 프록시 기술
5. 스프링이 지원하는 프록시
6. 빈 후처리기
7. @Aspect AOP
8. 스프링 AOP 개념
9. 스프링 AOP 구현
10. 포인트컷
11. 실무 주의사항
전 챕터를 통해 자동으로 프록시를 적용하는 과정을 살펴봤다.
- 포인트컷과 어드바이스로 구성되어 있는 어드바이저를 만들어서 스프링 빈으로 등록
- 자동 프록시 생성기가 스프링 빈으로 등록된 어드바이저를 조회한다
- 포인트컷이 매칭되는 경우 프록시 적용
이제 직접 어드바이저를 생성하는 대신 @Aspect 프록시를 통해 애너테이션 기반의 프록시를 사용해보자.
1. @Aspect 프록시
1) @Aspect란?
스프링이 제공하는 @Aspect 애너테이션을 사용하면 편리하게 어드바이저를 생성할 수 있다
- @Aspect는 관점 지향 프로그래밍(AOP)을 가능하게 하는 AspectJ 프로젝트에서 제공
- 이것을 통해 프록시를 통한 AOP가 가능해짐
2) @Aspect 프록시 적용
LogTraceAspect
@Aspect // 애너테이션 기반 프록시를 적용할 때 필요
public class LogTraceAspect {
// ...
@Around("execution(* hello.proxy.app..*(..))") // 본 애너테이션은 포인트컷 역할, 메서드는 어드바이스 역할
public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
TraceStatus status = null;
try {
String message = joinPoint.getSignature().toShortString(); // 클래스명을 포함한 메서드의 시그니쳐를 리턴 후 String으로 변환
status = logTrace.begin(message);
//로직 호출
Object result = joinPoint.proceed(); // target 호출, invocation.proceed()와 유사
logTrace.end(status);
return result;
} catch (Exception e) {
logTrace.exception(status, e);
throw e;
}
}
}
- @Aspect
- 애너테이션 기반 프록시를 적용할 때 사용된다
- 자동 프록시 생성기가 해당 애너테이션이 붙은 스프링 빈을 조회한다
- @Around
- 포인트컷 역할을 하며, 값에 Aspect 표현식이 들어간다
- @Around의 메서드는 어드바이스가 된다
- ProceedingJoinPoint joinPoint
- 어드바이스에서 살펴본 MethodInvocation invocation과 유사한 기능
- 내부에 실제 호출 대상, 인수 정보, 인스턴스 및 메서드 호출 정보가 포함되어 있다
- 참고로 @Aspect 하나에서 메서드를 여러 개 선언함으로써 여러 어드바이저 생성할 수 있다
AopConfig
@Configuration
@Import({AppV1Config.class, AppV2Config.class})
public class AopConfig {
@Bean
public LogTraceAspect logTraceAspect(LogTrace logTrace) {
return new LogTraceAspect(logTrace);
}
}
3) @Aspect 프록시 설명
이렇게 간단하게 애너테이션 하나로 어드바이저 생성이 가능한 것은 자동 프록시 생성기 덕분이다.
자동 프록시 생성기(AnnotationAwareAspectJAutoProxyCreator)는 2가지 일을 한다.
- @Aspect를 보고 어드바이저로 변환해서 저장한다 (이러한 이유로 이름에 AnnotationAware가 붙었다)
- 어드바이저를 기반으로 프록시를 생성한다
4) @Aspect 어드바이저 생성 과정
1) 실행
- 스프링 애플리케이션 로딩 시점에 자동 프록시 생성기를 호출한다
2) 모든 @Aspect 빈 조회
- 자동 프록시 생성기가 @Aspect 애너테이션이 붙은 스프링 빈을 모두 조회한다
3) 어드바이저 생성
- Aspect 어드바이저 빌더를 통해 @Aspect 애너테이션 정보를 기반으로 어드바이저를 생성한다
4) @Aspect 기반 어드바이저 저장
- 생성한 어드바이저를 @Aspect 어드바이저 빌더 내부에 저장한다
- @Aspect 어드바이저 빌더는 BeanFactoryAspectAdvisorsBuilder 클래스
- @Aspect의 정보를 기반으로 어드바이저를 만들고, @Aspect 어드바이저 빌더 내부 저장소에 캐싱한다
- 캐시에 어드바이저가 존재하는 경우 캐싱된 어드바이저를 반환한다
5) 어드바이저를 기반으로 프록시 생성
1) 생성
- 빈 대상이 되는 객체를 생성한다
- 이때 대상은 @Bean과 @Component을 모두 포함한다
2) 전달
- 생성된 객체가 빈 저장소에 등록되기 직전에 빈 후처리기에 전달된다
3-1) Advisor 빈 조회
- 스프링의 빈 후처리기(자동 프록시 생성기)는 스프링 컨테이너에서 모든 Advisor를 조회한다
3-2) @Aspect Advisor 빈 조회
- @Aspect 어드바이저 빌더 내부에 저장된 Advisor를 모두 조회한다
4) 프록시 적용 대상 체크
- 조회한 Advisor에 포함된 포인트컷을 통해 프록시 적용 대상 여부를 판단한다
- 메서드 하나라도 포인트컷 조건을 만족하면 프록시 적용 대상이 된다
5) 프록시 생성
- 프록시 적용 대상이면 프록시를 생성하고 반환한다
- 만약 적용 대상이 아니면 원본 객체를 반환한다
6) 빈 등록
- 반환된 객체(프록시 or 원본)를 스프링 빈으로 등록한다
6) 정리
- @Aspect를 사용하면 편리하게 애너테이션 기반 프록시를 적용할 수 있다
- 지금껏 만들어온 애플리케이션 전반에 로그를 남기는 기능은 애플리케이션의 여러 기능들 사이에 걸쳐서 들어가는 관심사였다
- 이를 횡단 관심사(cross-cutting)라고 한다
- 다음 챕터부터는 횡단 관심사를 전문으로 해결하는 스프링 AOP에 대해 알아볼 것이다
'Spring > 스프링 핵심 원리 - 고급편' 카테고리의 다른 글
[스프링 핵심 원리 - 고급편] 스프링 AOP 구현 (0) | 2023.03.08 |
---|---|
[스프링 핵심 원리 - 고급편] 스프링 AOP 개념 (0) | 2023.03.08 |
[스프링 핵심 원리 - 고급편] 빈 후처리기 (0) | 2023.03.06 |
[스프링 핵심 원리 - 고급편] 스프링이 지원하는 프록시 (0) | 2023.03.06 |
[스프링 핵심 원리 - 고급편] 동적 프록시 기술 (0) | 2023.02.21 |