AOP(Aspect Oriented Programming)
- 관점 지향 프로그래밍
- 어떤 로직을 기준으로 핵심적인 관점, 부가적인 관점으로 나누어서 보고 그 관점을 기준으로 각가 모듈화 하겠다는 것이다.
- 모듈화란 어떤 공통된 로직이나 기능을 하나의 단위로 묶는 것을 말한다.
스프링 AOP 특징
- 프록시 패턴 기반의 AOP 구현체, 프록시 객체를 쓰는 이유는 접근 제어 및 부가기능을 추가하기 위해서
- 스프링 빈에만 AOP 적용가능
- 모든 AOP 기능을 제공하는 것이 아닌 스프링 IoC와 연동하여 언터프라이즈 애플리케이션에서 가장 흔한 문제(중복코드, 프록시 클래스 작성의 번거로운, 객체들 간 관계 복잡도 증가..)에 대한 해결책을 지원하는 것이 목적입니다.
AOP 주요 개념
- @Aspect : 흩어진 관심사를 모듈화 한것, 주로 부가기능을 모듈화 합니다.
- @Before : 메소드 실행 전에 동작을 수행하는 Advice
- @After : 메서드 실행 후에 동작을 수행하는 Advice
- @AfterReturning : 메서드가 성공적으로 반환된 후에 동작을 수행하는 Advice
- @AfterThrowing : 메서드에서 예외가 발생한 후에 동작으로 수행하는 Advice
- @Around : 메서드 실행 전후에 동작을 수행하며, 메서드 실행을 직접 제어하는 Advice
- @Target : Aspect를 적용하는 곳(클래스, 메서드...)
- @Advice : 실직적으로 어떤 일을 해야할 지에 대한 것, 실질적인 부가 기능을 담은 구현체
- @JointPoint : Advice가 적용될 위치, 끼어들 수 있는 지점. 메서드 진입 지점, 생성자 호출 시점, 필드에서 값을 꺼내올 때 등 다양한 시점에 적용 가능
- @PointCut : JointPoint의 상세한 스펙을 정의한 것. 'A란 메서드의 진입 시점에 호출할 것' 과 같이 더욱 구체적으로 Advice가 실행될 지점을 정할 수 있다.
pointcut 표현식
1. execution(public(생략 가능) 리턴타입 패키지경로.클래스명.메소드명(매개변수))
- 가장 상세한 포인트컷을 지정할 수 있다. 리턴타입, 패키지 경로, 클래스명, 메소드명(매개변수) 까지
리턴타입
- * : 모든 리턴 타입
- void : 리턴 타입이 없음
- !void : 리턴 타입이 있음
패키지 경로
- com.study.transaction.service.impl : com.study.transaction.service.impl 까지의 패키지 경로
- com.study.transaction.service.impl.. : com.study.transaction.service.impl로 시작하는 모든 패키지
- com.study.transaction.service..impl : com.study.transaction.service 패키지에서 이름이 imp로 끝나는 패키지
클래스 경로
- *lmpl : 클래스명이 lmpl로 끝나는 클래스
- TransactionServicelmpl : TransactionServicelmpl 클래스
- TransactionService+ : TransactionService 클래스로 파생된 모든 자식 클래스 또는 인터페이스가 구현된 모든 클래스
메소드명(매개변수)
- *(..) : 모든메소드
- insert*(..) : insert로 시작하는 모든 메소드
- *(int) : 모든 메소드 중 int 타입 인자값을 갖는 메소드
2. within : 패턴내에 해당하는 모든 것들을 지정한다.
- com.study.transaction.service : com.study.transaction.service 패키지에 있는 모든 메소드
- com.study.transaction..* : com.study.transaction 패키지 및 하위 패키지에 있는 모든 메소드
3. bean : 생성된 bean으로 지정한다.
- bean(testTransaction) : 이름이 testTransaction인 빈의 메소드
- bean(*test) : 이름이 test로 끝나는 빈의 메소드
AOP 환경설정
Spring pom.xml
- aspectjrt 의존성
- aspectjweaver 의존성 : AspectJ의 pointcut 표현식 사용을 위해 aspectjweaver 라이브러리 추가한다.
- aspectjtools 의존성
//AspectJ 런타임 라이브러리 AOP 관련 기능이 작동하는데 필요한 기본적인 라이브러리
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version> //1.9.19
</dependency>
<!-- AspectJ Weaver : Java 코드에서 AOP 기능을 적용하기 위한 도구 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${org.aspectj-version}</version> //1.9.19
</dependency>
<!-- AspectJ Tools : AspectJ와 관련된 다양한 개발 도구들이 포함된 라이브러리 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${org.aspectj-version}</version> //1.9.19
</dependency>
root-context.xml
Autoproxy 설정
- @Aspect가 적용된 빈을 Aspect로 사용할 수 있게하는 설정
<!-- AspectJ 라이브러리를 이용한 Proxy 객체를 생성 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
AOP를 이용한 로직 구현
해당 클래스가 Aspect 라는 것을 선언
로깅
@Slf4j
@Component
@Aspect
public class ServiceLoggerAdvice {
@Before("execution(* kr.or.ddit.*..*(..))")
public void startLog(JoinPoint jp) {
log.info("startLog");
log.info("startLog : " + jp.getSignature());
log.info("startLog : " + Arrays.toString(jp.getArgs()));
}
- @Before() : 메소드 실행전 동작을 수행하는 Advice
- execution(* kr.or.ddit.*..*(..)) : kr.or.ddit.하위 패키지 Aspect 적용하겠다는 의미
- JoinPoint : AOP에서 제공하는 매개변수로 현재 실행되는 메서드에 대한 정보 제공
- JoinPoint.getSignature() : 어떤 클래스의 어떤 메서드가 실행 되었는지 보여줍니다.
- 예시) UserDetails org.springframework.security.core.userdetails.UserDetailsService.loadUserByUsername(String)
- JoinPoint.getSignature() : 전달된 파라미터 정보를 보여줌니다.
- 예시) startLog : [1651004]
- JoinPoint.getSignature() : 어떤 클래스의 어떤 메서드가 실행 되었는지 보여줍니다.
@Around("execution(* kr.or.ddit.*..*(..))")
public Object timeLog(ProceedingJoinPoint pjp) throws Throwable{
//메소드 실행 직전 시간 체킹
long startTime = System.currentTimeMillis();
log.info("pjpStart : " + Arrays.toString(pjp.getArgs()));
//메소드 실행
Object result = pjp.proceed();
//메소드 실행 직후 시간 체킹
long endTime = System.currentTimeMillis();
log.info("pjpEnd : " + Arrays.toString(pjp.getArgs()));
//직후 시간 - 직전 시간 => 메소드 실행 시간
log.info(pjp.getSignature().getName() + " : " + (endTime - startTime));
return result;
}
출처
https://engkimbs.tistory.com/entry/%EC%8A%A4%ED%94%84%EB%A7%81AOP
https://velog.io/@dkwktm45/Spring-AOP%EB%A5%BC-%EC%95%8C%EA%B3%A0-%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95%EC%9D%84-%EC%95%8C%EC%9E%90
'이론 > 스프링' 카테고리의 다른 글
[Spring] AOP Transaction 설정 (0) | 2024.10.07 |
---|---|
[Spring] 의존성 주입(DI) 3가지 방법 (0) | 2024.09.21 |
[Spring]IoC 컨테이너(Inversion of Control) (0) | 2024.09.21 |
[Spring]스프링 MVC의 흐름 (0) | 2024.04.23 |