2020. 4. 18. 17:03ㆍJava/Spring
1. AOP란
프로그래밍을 하다 보면, 공통적인 기능이 많아집니다. 이러한 공통기능을 모듈에 적용하기 위한 방법으로 상속을 이용할 수 있습니다. 하지만 JAVA에서는 다중 상속이 불가능합니다. 그리고 이러한 모듈을 계속 상속받아 공통 기능을 부여하기에는 한계가 있을 뿐더러 보기에도 불편하고 효율성도 떨어집니다. 이를 해결하기 위해 나타난 AOP는 핵심 기능과 공통 기능을 분리해, 공통 기능을 필요로 하는 핵심 기능들에 적용하는 방식입니다. 아래 그림과 같이, 붉은 상자에 있는 공통 부분들을 분리해내는 것입니다.
2. AOP의 용어
- Aspect: 공통 기능의 모듈
- Advice: Aspect를 구현한 객체
- JoinPoint: Advice를 적용해야 하는 부분(ex: 필드, 메소드 - spring에서는 메소드만 해당)
- Pointcut: JoinPoint의 부분으로 실제로 Advice가 적용된 부분
- Weaving: Advice를 핵심 기능에 적용하는 행위
3. AOP 적용 방법
컴파일 타임
자바 파일을 클래스 파일로 만들 때, 바이트 코드들을 조작하여 조작된 바이트 코드들을 생성합니다.
로드 타임
자바 파일을 클래스 파일은 변함이 없습니다. 다만 로딩하는 JVM 메모리 상에서는 공통 기능을 추가합니다.
런타임
프록시를 이용해 AOP를 적용합니다. 참고로 Spring에서 사용되는 방법입니다.
Clinet -> proxy -> Target(핵심 기능)
- Clinet가 proxy에 요청해서 공통 기능을 실행
- Proxy가 다시 Target으로 가서 핵심 기능을 실행
- 다시 공통 기능을 실행하기 위해, Proxy로 와서 공통 기능 실행
- Spring에서 AOP를 적용하는 방법
스프링 AOP를 사용하기 위해서 다음과 같은 Dependency를 추가해야 합니다.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>{{spring.version}}</version>
</dependency>
다음에는 아래와 같이 @Aspect 어노테이션을 붙여 이 클래스가 Aspect를 나타내는 클래스라는 것을 명시하고 @Component를 붙여 스프링 빈으로 등록합니다.
@Component
@Aspect
public class PerfAspect {
@Around("execution(* com.saelobi..*.EventService.*(..))")
public Object logPerf(ProceedingJoinPoint pjp) throws Throwable{
long begin = System.currentTimeMillis();
Object retVal = pjp.proceed(); // 메서드 호출 자체를 감쌈
System.out.println(System.currentTimeMillis() - begin);
return retVal;
}
}
@Around는 Advice중의 하나로 어노테이션을 타겟 메서드를 감싸서 특정 Advice를 실행한다는 의미입니다. 그리고 execution(* com.saelobi...EventService.(..)) 이 의미하는 것은 com.saelobi 아래의 패키지 경로의 EventService 객체의 모든 메소드에 이 Aspect를 적용하겠다는 의미입니다. execution은 PointCut을 지정하는 역할을 합니다.
Advice의 종류
- @Before: 타겟 메소드가 호출되기 전에 어드바이스 기능을 수행
- @After: 타겟 메소드의 결과에 관계 없이 타겟 메소드가 완료 되면 어드바이스 기능을 수행
- @AtfterThrowing: 타겟 메소드가 수행 중 예외를 던지게 되면 어드바이스 기능을 수행
- @Around: 어드바이스가 타겟 메소드를 감싸서 타겟 메소드 호출 전과 호출 후에 어드바이스 기능을 수행
포인트컷 지정자의 종류
- Args(): 메소드의 파라미터가 타겟 명세에 포함된 타입일 경우
- @args(): 메소드의 파라미터가 타겟 명세에 포함된 어노테이션 타입을 갖는 경우
- Execution(): 접근 제한자, 리턴 타입, 파라미터 타입, 클래스/인터페이스, 메소드 명 등을 전부 조합한 가장 세심한 지정자. 풀패키지에 메소드 명까지 직접 가능.
- Within(): 지정된 클래스/인터페이스까지만 적용
- @within(): 주어진 어노테이션을 사용하는 타입으로 선언된 메소드
- This(): 타겟 메소드가 지정된 빈 타입의 인스턴스인 경우
- Target(): 빈 타입이 아닌 타입의 인스턴스인 경우
- @target(): 타겟 메소드를 실행하는 객체의 클래스가 타겟 명세에 지정된 타입의 어노테이션이 있는 경우
- @annotation(): 타겟 메소드에 특정 어노테이션이 지정된 경우
참조: https://jojoldu.tistory.com/71
참조: https://engkimbs.tistory.com/746
'Java > Spring' 카테고리의 다른 글
Spring Singleton (0) | 2020.05.01 |
---|---|
@ExceptionHandler (0) | 2020.04.26 |
@Transactional (0) | 2020.04.17 |
Spring DI 방법 (0) | 2020.03.27 |
Spring 설정을 XML에서 Java Config로 바꾸기 (0) | 2020.03.27 |