반응형
필자는 AOP에 학습 과정에서 오해와 부족했던 부분을 체우기 위해서 학습을 진행했습니다
AOP
정의
- 관점 지향 프로그래밍의 준말로서 반복되는 공통관심사를 분리해서 모듈화 하는 기술을 의미합니다
특징
- Interface를 상속받아서 Proxy객체를 생성해 Advice의 기능을 추가해 주는 형태를 가집니다
- Proxy 자동 생성기를 통해서 Proxy 객체를 생성해주면 Bean 후처리기가 자동으로 Target 객체가 아닌 Proxy를 Bean으로 등록합니다
- Proxy 자동 생성기를 사용하지 않으면 수동으로 Proxy 객체를 생성해서 Bean으로 등록 해야 합니다.
Proxy 종류
- Interface가 존재하는 경우(JDK 동적 Proxy)
- Interface가 존재하는 Bean일 경우
- Proxy 객체는 Interface를 상속 받아서 사용
- 문제점
- 무조건 interface가 필요
- Interface가 없는 경우(CGLib)
- class 자체를 interface처럼 상속해서 사용함
- GCLib이라고 class file일 때 Byte code를 집어 넣는 외부 라이브러리가 필요(AOP에서 외부 라이브러리 의존도 발생)
- 문제점
- final class와 final method가 존재할 경우 상속 불가해서 에러 발샹
- default 생성자가 필수적으로 사용 됩니다(spring 4 이전 까지는) -> 상속을 사용하기 때문에 부모 class의 생성자를 호출 하기 때문입니다
- GCLib을 추가한 이유
- 레거시 코드나 외부에서 Interface 없이 구현한 경우 AOP를 설정해 주기 위해서 사용
- class를 이용한 Proxy 구성을 하는 방법
- interface 없는 class를 AOP 추가하기
- interface가 있더라도 무시하고 class 상속으로 강제로 변경하게 하는 경우 ->
proxy-target-class="true"
자동 Proxy 생성기를 사용할 때 주의점
- CGLib이 없이 Interface가 아닌 target 객체를 autowired 하게되면 에러 발생
- target 객체는 더이상 bean 이아니기 때문
- proxy 객체만 Bean으로 등록
cf) Bean 후처리기(BeanPostProcessor
)
- 정의: spring container에 등록 목적으로 만든 객체를 빈저장소에 저장하기 전전에 조작할 수 있도록 해주는 기능 입니다
- 사용방법: 2개의 method가 있는 interface(
BeanPostProcessor
)를 상속 받고, 해당 class를 Bean으로 등록해야 합니다 - 목적
- 객체를 조작할 수 있고, 다른 객체로 바꿔서 저장할 수 있음
- component scan으로 등록될 spring bean을 조작할때 주로 사용합니다(bean 객체를 proxy로 변경)
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
- 호출 순서: spring Bean 후처리기
postProcessBeforeInitialization
-> 생성 callback 함수 호출 ->postProcessAfterInitialization
AspectJ
정의
- Spring 2.0부터 도입된 독립적인 AOP 확장 기술중 하나 입니다
- GCLib을 사용해서 바이트 코드를 넣어서 AOP를 구현하는 framework 입니다.
특징
- Spring AOP는 Bean객체에서만 AOP 설정이 가능하지만 AspectJ는 모든 class에 대해서 AOP가 가능합니다
- 과거에는 Aspect 라는 하나의 언어로서 컴파일이 별도로 필요 했었습니다
- 현재는 AspectJ를 통해서 Java Run time에서 byte code 조작으로 별도의 컴파일러 없이 사용 가능
- AspectJ가 Byte Code 주입을 사용하는 이유
- Proxy로 접근 못하는 부분을 PointCut 지시자로 설정 가능
- 필드를 읽는 시점, 객체 생시점 ...etc
- Spring에서 AspectJ AOP를 차용하는 경우에는 Domain class내부에 DI를 해야하는 경우 사용
- Domain class를 Bean으로 등록 하지 않고 AOP를 통해서 Bean 객체를 주입받을 수 있게 합니다
- Spring Boot 에서는
aspectjweaver
를 spring-boot-starter 디팬던시에 포함되어 있습니다
aspectJweaver
aspectJ
관련 라이브러리 등록을 목적으로 사용합니다- Spring MVC에서는
@EnableAspectJAutoProxy
를 사용해서 aspectJ에 관련된 객체를 Bean으로 등록 합니다 - 등록 과정에서 가장 중요한 부분은
AnnotationAwareAspectJAutoProxyCreator
입니다 - Sprin Boot는
AopAutoConfiguration
를 통해서 자동으로@EnableAspectJAutoProxy
설정이 잡힙니다
AnnotationAwareAspectJAutoProxyCreator
- 정의
- Spring AOP의 핵심으로서 Spring Boot에서는
AopAutoConfiguration
를 통해서 자동으로 Bean으로 등록 됩니다 - proxy를 자동으로 생성해서 Bean으로 등록해주는 후처리기 입니다
- 자동화 케이스
- Spring Bean에 등록된
Advisor(Advice + PointCut)
을 모두 찾습니다. 그리고PointCut
에 저장된 class, Method를 찾아서 1개라도 해당 된다면 proxy로 생성 합니다 @AspectJ
annotation와 관련된 AOP 기능도 자동으로 처리해줍니다
AOP의 발전
GCLIb 단점 해결
- final class, final method인 경우 대부분 개발자가 잘 사용하지 않기 때문에 문제가 크지 않음
- 현재 모든 AOP는 CGLib을 사용합니다
- spring 3.2부터 AspectJ를 기본 package로 모듈을 가지도록 확장 -> 그렇기 때문에 AspectJ가 외부Lib이지만 spring-boot-starter만 가지고 바로 AOP를 사용할 수 있음
- 생성자 2번 호출 이슈 해결 : spring 4부터 objenesis라는 오픈소스를 통해서 부모 class 생서자를 호출 하지 않고 객체를 생성할 수 있음
현재 AOP
- default로 cglib AOP를 사용하도록 강제
- AopAutoConfiguration에에서 application properties에
spring.aop.proxy-target-class
값이 false인지 true인지 확인후 false인경우 interface가 있으면, default로 JDK dynamic proxy 생성 가능합니다.
반응형
'Spring > 개념' 카테고리의 다른 글
Spring EventListener (0) | 2022.05.28 |
---|---|
Spring Transactional 동작 과정 (0) | 2022.04.10 |
Logging (0) | 2021.12.17 |
Servlet과 Spring Container (1) | 2021.12.04 |
Spring Test Mock 사용법 및 특징 (1) | 2021.10.30 |