스프링 AOP에서 제공하는 핵심 기능 중 하나는 다양한 통지 유형을 통해 프로그램 실행 흐름을 제어하는 것입니다. 이 기능을 활용하면 비즈니스 로직과 분리된 공통 기능(예: 로깅, 트랜잭션 관리)을 효과적으로 구현할 수 있습니다.
CustomAnnotation.java
package com.example.aop;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 커스텀 어노테이션 정의
* 메서드 레벨에서 사용 가능하며 런타임 시 유지
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomAnnotation {
}
ConfigSetup.java
package com.example.aop;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan
@EnableAspectJAutoProxy
public class ConfigSetup {
}
LoggingAspect.java
package com.example.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class LoggingAspect {
// 실행 전 처리
@Before("@annotation(CustomAnnotation)")
public void preExecution(JoinPoint jp) {
String methodName = jp.getSignature().getName();
System.out.println(methodName + " 메서드 실행 시작");
}
// 실행 후 처리
@After("@annotation(CustomAnnotation)")
public void postExecution(JoinPoint jp) {
String methodName = jp.getSignature().getName();
System.out.println(methodName + " 메서드 실행 완료");
}
// 반환 시 처리
@AfterReturning(value = "@annotation(CustomAnnotation)", returning = "result")
public void onReturn(JoinPoint jp, Object result) {
String methodName = jp.getSignature().getName();
System.out.println(methodName + " 반환 값: " + result);
}
// 예외 발생 시 처리
@AfterThrowing(value = "@annotation(CustomAnnotation)", throwing = "ex")
public void onError(JoinPoint jp, Exception ex) {
String methodName = jp.getSignature().getName();
System.out.println(methodName + " 예외 발생: " + ex.getMessage());
}
// 전체 흐름 감싸기
@Around("@annotation(CustomAnnotation)")
public Object aroundAdvice(JoinPoint jp) throws Throwable {
Object[] args = jp.getArgs();
Object result = jp.proceed(args);
return result;
}
}
AppMain.java
package com.example.aop;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class AppMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigSetup.class);
MathOperations math = context.getBean(MathOperations.class);
math.calculate(3, 4);
math.subtract(5, 2);
}
}
MathOperations.java
package com.example.aop;
public interface MathOperations {
int calculate(int x, int y);
void subtract(int x, int y);
}
MathServiceImpl.java
package com.example.aop;
import org.springframework.stereotype.Component;
@Component
public class MathServiceImpl implements MathOperations {
@CustomAnnotation
public int calculate(int a, int b) {
System.out.println(a + " + " + b + " = " + (a + b));
return a + b;
}
@CustomAnnotation
public void subtract(int a, int b) {
System.out.println(a + " - " + b + " = " + (a - b));
}
}
실행 결과:
calculate 메서드 실행 시작
3 + 4 = 7
calculate 반환 값: 7
calculate 메서드 실행 완료
subtract 메서드 실행 시작
5 - 2 = 3
subtract 메서드 실행 완료