Formoat's Open Blog
AOP(Aspect Oriented Programming) - 관점 지향 프로그래밍 본문
# AOP(Aspect Oriented Programming)
AOP는 관점 지향 프로그래밍으로 어떠한 로직이 있을 때 로직을 핵심적인 관점(로직)과 공통적인 관점(로직)으로
구분하여 각 구분된 관점을 모듈화 하는것을 의미한다. 이는 로직에서 공통되는 부분을 떼어내 따로 정의하고,
핵심 로직에서 공통된 로직이 필요할 경우에 이를 삽입하여 적용한다.
이 때 핵심 로직에서는 공통된 로직을 직접적으로 호출하지는 않는다. 핵심 로직에서 구현된 코드를 컴파일 하거나,
컴파일 된 클래스를 로딩, 또는 로딩한 클래스의 객체를 생성할 때 AOP가 적용되 핵심 로직을 구현한 코드안에
공통된 로직이 삽입된다.
# AOP 용어
1) Target : 핵심로직을 구현하는 클래스를 의미 (공통관심 기능이 적용되는 대상체)
2) Advice : '어떤' 공통 관심 기능을 '언제' 핵심 로직에 적용할 지 정의
Advice | Description |
Before Advice | 타겟 메서드의 비즈니스 로직 수행 전 Advice 실행 |
After Advice | 타겟 메서드의 비즈니스 로직 수행 전 Advice 실행 |
After Returning Advice | 타겟 메서드의 비즈니스 로직 정상적 수행 후 Advice 실행 |
After Throwing Advice | 타겟 메서드의 비즈니스 로직 수행 중 예외 발생시 Advice 실행 |
Around Advice | 타겟 메서드의 비즈니스 로직 수행 전/후 Advice 실행 |
3) JoinPoint : Advice를 적용할 수 있는 지점을 의미 (클라이언트에서 호출하는 모든 메서드)
메서드 호출, 필드 값 변경, 인스턴스 생성, 예외 발생 시점 등과 어플리케이션을 실행할 때
특정한 작업이 일어나는 시점을 조인 포인트라고 한다.
4) Pointcut : JoinPoint의 부분 집합으로서 실제 Advice가 적용되는 JoinPoint를 의미
- Pointcut은 JoinPoint에 조건을 걸어 조건에 해당하는 JoinPoint에 Advice를 적용한다.
- Pointcut 정의 시 정규 표현식이나 AspectJ문법을 이용해 Pointcut을 정의하게 된다.
< 포인트컷 표현식의 구성 >
(1) 지정자
- 포인트컷 지정자는 execution을 포함해 총 9가지의 지정자가 존재한다.
- 주로 사용하는 지정자는 exection, @annotation 두 가지가 대표적이다.
· execution : 접근제한자, 리턴타입, 클래스, 메소드, 파라미터 등을 전부 조합가능한 가장 세심한 지정자
· @annotation : 타겟 메소드에 특정 어노테이션이 지정된 경우 사용하는 지정자
(2) 타겟 명세
- 타겟에 대한 명세(조건)을 적는 부분으로 지정자마다 조금 차이가 있지만 표현방법은 동일하다.
· 리턴타입 : 리턴타입을 명시 또는 *(모든타입), !(~를 제외한 모든타입)
· 패키지 경로 : 패키지 경로를 명시 또는 ..(~시작, ~끝, 시작~끝인 모든 패키지)
· 클래스 : 클래스이름을 명시 또는 *(~시작, ~끝, 시작~끝인 모든 클래스), +(클래스명 뒤에 지정시 파생 클래스 포함)
· 메소드 : 메소드이름을 명시 또는 *(클래스와 동일)
· 매개변수 : 매개변수이름을 명시 또는 *(하나의 모든타입), ..(타입와 개수의 제약없음)
※ 매개변수의 경우 타입을 명시할 때 참조 타입일 경우 패키지와 클래스명을 모두 적어야 함.
5) Weaving : Advice를 핵심 로직 코드에 적용하는 것을 의미 (공통 로직을 핵심 로직에 삽입)
(1) 컴파일 시에 Weaving 하기 : 컴파일 할 때 공통 코드를 삽입하여 AOP 가 적용된 클래스 파일 생성
(2) 클래스 로딩 시에 Weaving 하기 : 원본 클래스는 변경하지 않고 클래스를 로딩할 때 JVM이 변경된 바이트 코드 사용
(3) 런타임 시에 Weaving 하기 : 소스 코드, 클래스 정보를 변경하지 않고 프록시를 이용해 적용 (스프링 지원 방식)
6) Aspect : 여러 객체에 공통으로 적용되는 기능 (Pointcut + Advice)
7) Proxy : 타겟을 감싸 타겟의 요청을 대신 받아주는 랩핑(Wrapping) 오프젝트
- 호출자 코드에서 타겟을 호출하게 되면 타겟이 아닌 타겟을 감싸고 있는 프록시가 호출된다.
- 타겟 메서드를 실행하기 전/후에 선처리와 후처리를 실행하도록 구성된다.
- AOP에서 프록시는 호출을 가로채 어드바이스에 등록된 기능을 수행한 후 타겟 메소드를 호출하게 된다.
< AOP 실행 흐름 >
※ 사용자가 여러 조인포인트를 호출(❶)하면 특정 포인트컷(❷)으로 지정한 메소드가 호출되는 순간,
어드바이스(❸) 객체의 어드바이스 메소드가 실행된다.
※ 어드바이스 메소드의 동작 시점을 5가지고 지정할 수 있으며, 포인트 컷으로 지정한 메소드가 호출 될 때,
어드바이스 메소드를 삽입하도록 하는 설정을 애스팩트(❹)라 하며, 이 애스팩트 설정에 따라 위빙(❺)이 처리된다.
# AOP 구현
스프링 AOP를 사용하기 위한 의존 추가(Maven)
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
1) XML 스키마 기반의 POJO 클래스를 이용한 AOP 구현
2) AspectJ 에서 정의한 @Aspect 어노테이션 기반의 AOP 구현
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<context:component-scan base-package="com.spring.aop"/>
<!-- 어노테이션 활성화 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
※ context 어노테이션과 마찬가지로 aop 어노테이션 사용시 어노테이션 활성화 코드를 삽입해야 함.
# Advice에 사용되는 객체
1) JoinPoint 클래스
- Around Advice를 제외한 나머지 Advice 타입을 구현한 메서드에서는 선택적으로 사용
- JoinPoint를 파라미터로 사용할 때에는 반드시 첫 번째 파라미터로 사용
Method | Description |
Signature getSignature() | 호출한 메서드의 시그니처(리턴타입, 이름, 매개변수 등) 정보가 저장된 객체를 반환 |
Object getTarget() | 호출한 메서드를 포함하는 대상 객체를 반환 |
Object[] getArgs() | 호출자 코드에서 넘겨준 인자 목록을 Object배열로 반환 |
2) ProceedingJoinPoint 클래스
- JoinPoint 인터페이스 구현
- Around Adivce에서만 사용 – proceed() 가 필요하기 때문
- Around Adivce를 구현한 메서드는 반드시 첫 번째 파라미터로 ProceedingJoinPoint타입을 지정해야 함
Method | Description |
String getName() | 호출한 메서드 이름을 반환 |
String toLongString() | 호출한 메서드의 반환타입, 이름, 매개변수를 패키지 경로를 포함해 반환 |
String getName() | 호출한 메서드 시그니처를 축약한 문자열로 반환 |
'Java > Spring' 카테고리의 다른 글
MyBatis - 마이바티스 (0) | 2019.10.07 |
---|---|
hikari CP (0) | 2019.10.04 |
DI (Dependency Injection) - 의존성 주입 (0) | 2019.10.01 |
5 (0) | 2019.10.01 |
4 (0) | 2019.10.01 |