돌아가는 방식은 대충 파악 했으니 이제 라이브러리로 사용해보자 먼저 aop에서 사용하는 용어들 정리
용어 | 역할 |
Target | Advice가 적용될 객체 |
Advice | Target에 동적으로 추가될 부가기능(코드) |
Join Point | Advice가 추가(join)될 대상(메서드) |
Pointcut | Join Point들을 정의한패턴. 예) execution(* com.fastcampus.*.*(..)) |
Proxy | Target에 Advice가 동적으로 추가되어 생성된 객체 |
Weaving | Target에 Advice를 추가해서 Proxy를 생성하는 것 |
아래는 Advice의 종류
종류 | 애너테이션 | 설 명 |
Around Advice | @Around | 메서드의 시작과 끝부분에서 실행(메서드 호출 전후 및 예외 발생 시점) → 주로 성능 측정, 트랜잭션 관리, 보안 체크 등에 사용 |
Before Advice | @Before | 메서드의 시작 부분에서 실행(타겟 메서드 실행 전) → 검증, 인증, 인가 검사, 파라미터 유효성 검사 등에 사용(전처리) |
After Advice | @After | 메서드의 끝 부분에서 실행(타겟 메서드 실행된 후) → 예외발생과 관련없이 실행, 자원 해제, 로깅 등의 후처리 작업 |
After Returning | @AfterReturning | 예외가 발생 하지 않았을 때만(타겟 메서드가 정상적으로 반환된 후에 실행) → 메서드의 반환 값을 가공하거나 추가적인 로깅 등을 수행 |
After Throwing | @AfterThrowing | 예외가 발생 했을 때 실행(타겟 메서드에서 예외가 발생한 후) → 예외 발생 시 로깅 및 예외 처리 등을 수행 |
아래 3가지 라이브러리가 있어야 한다
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
간단한 계산기와 계산할때 시작 전후 로그와 메서드 동작시간을 출력해주는 AOP를 적용해보자
1. 메인기능 담당
2. 부가기능 담당(+AOP 관련 xml 파일)
실행 클래스 총 3개 작성
AspectJ 기반 AOP를 자동으로 설정하기 위해 root-context_aop.xml 파일 생성 후 아래 내용을 작성
→ 이 파일은 root-context.xml 에 같이 작성해도 되지만 우선 별도로 분리해서 작성
root-context_aop.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<aop:aspectj-autoproxy/>
<context:component-scan base-package="com.fastcampus.ch3.aop" />
</beans>
→ 여기서 aop사용시 <aop:aspectj-autoproxy/>를 작성하게 되는데 가장 윗부분 bean 스키마 목록에 xmlns:aop를 반드시 적어야함..
메인 기능을 담당할 MyMath 클래스 - @Component 선언(스프링에서 빈 관리)
import org.springframework.stereotype.Component;
@Component // 스프링 빈객체 등록
public class MyMath {
// 계산기능(핵심기능)
public int add(int a, int b) { return a + b; }
public int add(int a, int b, int c) { return a + b + c; }
public int sub(int a, int b) { return a - b; }
public int multy(int a, int b) { return a * b; }
}
부가기능을 담당할 LoggingAdvice 클래스(AOP)
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Component // 스프링 빈객체 등록
@Aspect // AOP 클래스 선언
public class LoggingAdvice {
@Around("execution(* com.fastcampus.ch3.aop.MyMath.add*(..))")
// AOP를 적용하고자 하는 부분
// pointcut - 부가기능이 적용될 메서드의 패턴
// com.fastcampus.ch3.aop.MyMath 클래스의 이름이 add로 시작하는 모든 메서드를 타겟으로 지정
public Object methodCallLog(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
System.out.println("<<[start] " + pjp.getSignature().getName()+ Arrays.toString(pjp.getArgs()));
Object result = pjp.proceed(); // target의 메서드를 호출
System.out.println("result="+result);
System.out.println("[end]>> " + (System.currentTimeMillis() - start) + "ms");
return result;
}
}
LoggingAdvice 클래스에 @Component, @Aspect 선언하고 처음에 AOP의 용어가 어느 부분에 해당되는지 보면
1. Target : com.fastcampus.ch3.aop.MyMath 클래스의 인스턴스
2. Advice : @Around 애너테이션으로 정의된 메서드(methodCallLog 메서드)
3. JoinPoint : com.fastcampus.ch3.aop.MyMath 클래스의 add로 시작하는 메서드 호출
4. PointCut : "execution(* com.fastcampus.ch3.aop.MyMath.add*(..))" 표현식(add로 시작하는 모든 메서드)
5. Proxy : AOP 프레임워크가 생성한 com.fastcampus.ch3.aop.MyMath 클래스의 프록시 객체
6. Weaving : 런타임에 프록시를 통해 Advice를 적용
이걸 실행할 AopMain2 클래스를 만들고 실행
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
public class AopMain2 {
public static void main(String[] args) {
ApplicationContext ac = new GenericXmlApplicationContext("file:src/main/webapp/WEB-INF/spring/**/root-context_aop.xml");
MyMath mm = (MyMath)ac.getBean("myMath");
mm.add(3,5);
mm.add(1,2,3);
System.out.println("mm.multy(3,5) = "+mm.multy(3,5));
}
}
수업때 했던 것들 찾아보면 나올텐데.. 봐서 보충할거 있으면 보충해야겠다