본문 바로가기
Spring/개념

AOP

by clearinging 2022. 2. 2.
반응형

필자는 AOP에 학습 과정에서 오해와 부족했던 부분을 체우기 위해서 학습을 진행했습니다

AOP

정의

  • 관점 지향 프로그래밍의 준말로서 반복되는 공통관심사를 분리해서 모듈화 하는 기술을 의미합니다

특징

  • Interface를 상속받아서 Proxy객체를 생성해 Advice의 기능을 추가해 주는 형태를 가집니다
  • Proxy 자동 생성기를 통해서 Proxy 객체를 생성해주면 Bean 후처리기가 자동으로 Target 객체가 아닌 Proxy를 Bean으로 등록합니다
    • Proxy 자동 생성기를 사용하지 않으면 수동으로 Proxy 객체를 생성해서 Bean으로 등록 해야 합니다.

Proxy 종류

  1. Interface가 존재하는 경우(JDK 동적 Proxy)
  • Interface가 존재하는 Bean일 경우
  • Proxy 객체는 Interface를 상속 받아서 사용
  • 문제점
    • 무조건 interface가 필요
    •  
  1. 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

  1. 정의
  • Spring AOP의 핵심으로서 Spring Boot에서는 AopAutoConfiguration를 통해서 자동으로 Bean으로 등록 됩니다
  • proxy를 자동으로 생성해서 Bean으로 등록해주는 후처리기 입니다
  1. 자동화 케이스
  • 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