postProcessBeforeInitialization
: 객체 생성 이후에 @PostConstruct
같은 초기화가 발생하기postProcessAfterInitialization
: 객체 생성 이후에 @PostConstruct
같은 초기화가 발생한 다음스프링 빈 생성 이후에 초기화 하는 역활(한번만 호출)
스프링은 CommonAnnotationBeanPostProcessor 라는 빈 후처리기를 자동으로 등록하는데 여기서 @PostConstruct이 붙은 메서드 호출함. 스프링 스스로도 스프링 내부의 기능을 확장하기위해 빈 후처리기 사용
빈 후처리기를 통해 원본 빈 객체를 프록시 객체로 변환 -> 스프링 컨테이너에는 원본 객체 대신에 프록시가 등록이 된다
프록시 타겟만 프록시를 빈으로 등록함(basePackage) 그렇지 않으면 스프링의 모든 빈들이 빈 후처리기에 들어와서 프록시 빈 등록이 된다.
- 빈 후처리기는 따로 빈 등록해줘야함!
implementation 'org.springframework.boot:spring-boot-starter-aop'
aspectjweaver 라는 aspectJ 관련 라이브러리를 등록
AnnotationAwareAspectJAutoProxyCreator 라는 빈 후처리기가 스프링 빈에 자동 등록
이 빈 후처리기는 스프링 빈으로 등록된 Advisor
들을 자동으로 찾아서 프록시가 필요한 곳에 자동으로 프록시 를 적용해준다. 왜냐 어드바이저는 이미 포인트컷이 존재하기 때문에 어디에 프록시를 적용해야할지 암
빈 후처리기에서 스프링 컨테이너에서 모든 어드바이저를 조회한다
모든 어드바이저에 있는 포인트컷을 조사해 프록시 대상여부를 판단함. 이때 해당 객체의 클래스 정보, 메서드를 포인트컷에 하나하나 모두 매칭해봄
프록시 적용 대상이면 프록시를 생성하고 반환해서 프록시를 스프링 빈으로 등록 한다. 만약 프록 시 적용 대상이 아니라면 원본 객체를 반환해서 원본 객체를 스프링 빈으로 등록한다.
- 프록시 적용 대상 여부를 체크해서 꼭 필요한 곳에만 프록시를 적용한다.(빈후처리기-자동프록시생성)
- 프록시의 어떤 메서드가 호출 되었을 때 어드바이스를 적용할 지 판단한다. (프록시 내부)
- 클래스, 메스드 조건을 모두 비교한다. 여기서 하나의 메서드라도 대상이되면 프록시 생성
-> 프록시 대상이면 프록시 -> 어드바이스 호출 -> 타겟
-> 프록시 대상이 아니면 -> 어드바이스 호출x ->타겟
어드바이저만 만들면 스프링 빈 후처리기가 알아서 프록시 생성해서 빈으로 등록해 준다.
@Aspect를 사용해서 어드바이저를 쉽게 만들 수 있다.
실제로는 자동 빈 후처리기가 @Aspect를 찾아서 어드바이저로 만들어줌
@Around 의 값에 포인트컷 AspectJ표현식을 넣는다.
@Around : 포인트컷 + 공통로직(프록시로직) = 어드바이스
ProceedingJoinPoint : 어드바이스에서 살펴본 MethodInvocation invocation
과 유 사한 기능이다. 내부에 실제 호출 대상, 전달 인자, 그리고 어떤 객체와 어떤 메서드가 호출되었는지 정보가 포함
되어 있다.
자동 프록시 생성기(빈 후처리기)는 스프링 컨테이너에서 @Aspect 애노테이션이 붙은 스프링 빈을 모두 조회한다.
그 이후에, @Aspect 어드바이저 빌더를 통해 @Aspect 애노테이션 정보를 기반으로 어드바이저 생성
BeanFactoryAspectJAdvisorsBuilder
클래스이다. @Aspect
의 정보를 기반으로 포인트컷, 어드바이스, 어드바이저를 생성하고 보관하는 것을 담당한다. @Aspect
의 정보를 기반으로 어드바이저를 만들고, @Aspect 어드 바이저 빌더 내부 저장소에 캐시한다. 캐시에 어드바이저가 이미 만들어져 있는 경우 캐시에 저장된 어드바이저를 반환 한다.스프링 컨테이너에서 어드바이저 빈 을 모두 조회한다
@Aspect 어드바이저 빌더 내부에 저장된 어드바이저 모두 조회한다. 이때 안에 있는 포인트컷으로 프록시 적용대상 여부 판단
적용대상이면 프록시 빈 등록 아니면 그대로 빈 등록
부가 기능은 보통 여러 클래스에 걸쳐서 함께 사용된다. 이런 부가 기능은 횡단관심사(cross-cutting concerns)가 된다.
애플리케이션 로직은 크게 핵심 기능과 부가 기능으로 나눌 수 있다.
애플리케이션을 바라보는 관점을 하나하나의 기능에서 횡단 관심사 관점으로 달리 보자라는 마인드로 프로그래밍을 보는 방식을 관점지향 프로그래밍 AOP라 한다.
AOP는 OOP를 대체하기 위한것이 아니라 횡단 관심사를 깔끔하게 처리하기 어려운 OOP의 부족한 부분을 보조하는 목적으러 개발 됬다.
.java
소스 코드를 컴파일러를 사용해서 .class
를 만드는 시점에 부가 기능 로직을 추가할 수 있다. 이때는 AspectJ가 제공하는 특별한 컴파일러를 사용해야 한다.
실제 대상 코드에 애스팩트를 통한 부가 기능 호출 코드가 포함된다. AspectJ를 직접 사용해야 한다.
이렇게 원본 로직에 부가 기능 로직이 추가되는 것을 위빙 이라 한다.
.class 파일을 JVM 내부의 클래스 로더에 저장하기전에 조작한다.
실제 대상 코드에 애스팩트를 통한 부가 기능 호출 코드가 포함된다. AspectJ를 직접 사용해야 한다.
- 프록시 방식을 사용하는 스프링 AOP의 조인 포인트는 메서드 실행으로 제한된다.
- 프록시 방식을 사용하는 스프링 AOP는 스프링 컨테이너가 관리할 수 있는 스프링 빈에만 AOP를 적용할 수 있다.
스프링은 AspectJ의 문법을 차용하고 프록시 방식의 AOP를 적용한다. AspectJ를 직접 사용하는 것이 아니다.
AOP 프록시는 기능을 구현하기 위해 만든 프록시 객체, 스프링에서 AOP 프록시는 JDK 동적 프록시 또는 CGLIB 프록시이다.