반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- jpa
- vaultTemplate
- 포맷터
- findAny
- JsonType
- JsonStringType
- AOP
- gradle
- LogInterceptor
- ClientHttpRequestInterceptor
- AOP target
- fotmatter
- spring
- java
- Starter
- @AutoConfiguration
- restTemple
- ResponseBodyAdvice
- AOP 매개변수
- 개방/폐쇄 원칙
- Thread Safety
- AOP this
- auto configuration
- 쓰레드 안전
- AccessLevel
- findFirst
- RestTemplate
- Spring Boot
- Stream
- Save Action
Archives
- Today
- Total
맨땅에 헤딩하는 개바른자
[AOP] 매개변수 전달 본문
반응형
이 문서에서는 AOP(Aspect Oriented Programming)에서 매개변수 전달에 대해 다룹니다.
포인트컷 표현식을 사용해서 어드바이스에 매개변수를 전달 할 수 있는 방법을 알아보겠습니다.
this. target, args, @targer, @within, @annotation, @args
다음과 같은 예제코드가 있다.
@Before("allMember() && args(arg...)")
public void logArgs3(String arg) {
log.info("[logArgs3] arg={}", arg);
}
- 포인트컷의 이름과 매개변수의 이름을 맞추어야 한다. 여기서는 “arg”로 맞추었다.
- 추가로 타입이 메서드에 지정한 타임으로 제한된다. 여기서는 메서드의 타입이 “String”으로 되어있기 때문에 다음과 같이 정의되는 것으로 이해하면된다.
- args(arg…) > args(String,…)
다양한 메개변수 전달 예시를 확인해보겠습니다.
일부 어노테이션과 서비스는 사전에 준비된 코드로 아래 git주소를 확인해주세요.
https://github.com/ymwoo88/study-springboot-aop/tree/feature/스프링-AOP-매개변수
package hello.aop.pointcut;
import hello.aop.member.MemberService;
import hello.aop.member.annotation.ClassAop;
import hello.aop.member.annotation.MethodAop;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
@Slf4j
@Import(ParameterTest.ParameterAspect.class)
@SpringBootTest
public class ParameterTest {
@Autowired
MemberService memberService;
@Test
void success() {
log.info("memberService Proxy={}", memberService.getClass());
memberService.hello("helloA");
}
@Slf4j
@Aspect
static class ParameterAspect {
@Pointcut("execution(* hello.aop.member..*.*(..))")
private void allMember() {
}
/**
* ProceedingJoinPoint에서 필요한것을 모두 사용
*/
@Around("allMember()")
public Object logArgs1(ProceedingJoinPoint joinPoint) throws Throwable {
Object args1 = joinPoint.getArgs()[0];
log.info("[logArgs1]{}, arg={}", joinPoint.getSignature(), args1);
return joinPoint.proceed();
}
/**
* args를 사용하면 parameter에서 바로 받아서 사용할 수 있다.
*/
@Around("allMember() && args(arg, ..)")
public Object logArgs2(ProceedingJoinPoint joinPoint, Object arg) throws Throwable {
log.info("[logArgs2]{}, arg={}", joinPoint.getSignature(), arg);
return joinPoint.proceed();
}
/**
* Befores는 핵심이아니나 좀더 간단하게 값을 받아 사용할 수 있다.
*/
@Before("allMember() && args(arg, ..)")
public void logArgs3(String arg) {
log.info("[logArgs3], arg={}", arg);
}
/**
* - this, target 비슷한애들이다.
* - object 타입으로 선언하여 parameter에서 사용할 수 있지만 둘에 큰 차이점은 직접객체냐, 프록시객체냐 차이가 존재한다.
* 2023-03-29 19:56:42.731 INFO 10265 --- [ Test worker] h.a.p.ParameterTest$ParameterAspect : [targetArgs]String hello.aop.member.MemberServiceImpl.hello(String), obj=class hello.aop.member.MemberServiceImpl
* 2023-03-29 19:56:42.731 INFO 10265 --- [ Test worker] h.a.p.ParameterTest$ParameterAspect : [thisArgs]String hello.aop.member.MemberServiceImpl.hello(String), obj=class hello.aop.member.MemberServiceImpl$$EnhancerBySpringCGLIB$$38b3c3e4
*
* 정리
* - this : 프록시 객체를 전달 받는다
* - target : 실제 대상 객체를 전달 받는다 (프록시 이전 오리지날 객체)
* - @target, @within : 타입의 어노테이션을 전달 받는다.
* - @Annotation : 메서드의 어노테이션을 전달 받는다. 여기서는 "annotation.getValue()"로 해당 값을 출력하는 결과를 확인 할 수있다.
*/
@Before("allMember() && this(obj)")
public void thisArgs(JoinPoint joinPoint, MemberService obj) {
log.info("[thisArgs]{}, obj={}", joinPoint.getSignature(), obj.getClass());
}
@Before("allMember() && target(obj)")
public void targetArgs(JoinPoint joinpoint, MemberService obj) {
log.info("[targetArgs]{}, obj={}", joinpoint.getSignature(), obj.getClass());
}
@Before("allMember() && @target(annotation)")
public void atTarget(JoinPoint joinPoint, ClassAop annotation) {
log.info("[@target]{}, annotation={}", joinPoint.getSignature(), annotation);
}
@Before("allMember() && @within(annotation)")
public void atWithin(JoinPoint joinPoint, ClassAop annotation) {
log.info("[@within]{}, annotation={}", joinPoint.getSignature(), annotation);
}
@Before("allMember() && @annotation(annotation)")
public void atAnnotation(JoinPoint joinPoint, MethodAop annotation) {
log.info("[@annotation]{}, annotation={}, annotation.getValue={}", joinPoint.getSignature(), annotation, annotation.value());
}
}
}
결과물
2023-03-29 20:27:26.210 INFO 34796 --- [ Test worker] hello.aop.pointcut.ParameterTest : memberService Proxy=class hello.aop.member.MemberServiceImpl$$EnhancerBySpringCGLIB$$62737d07
2023-03-29 20:27:26.212 INFO 34796 --- [ Test worker] h.a.p.ParameterTest$ParameterAspect : [logArgs1]String hello.aop.member.MemberServiceImpl.hello(String), arg=helloA
2023-03-29 20:27:26.213 INFO 34796 --- [ Test worker] h.a.p.ParameterTest$ParameterAspect : [logArgs2]String hello.aop.member.MemberServiceImpl.hello(String), arg=helloA
2023-03-29 20:27:26.213 INFO 34796 --- [ Test worker] h.a.p.ParameterTest$ParameterAspect : [@annotation]String hello.aop.member.MemberServiceImpl.hello(String), annotation=@hello.aop.member.annotation.MethodAop("test value"), annotation.getValue=test value
2023-03-29 20:27:26.213 INFO 34796 --- [ Test worker] h.a.p.ParameterTest$ParameterAspect : [@target]String hello.aop.member.MemberServiceImpl.hello(String), annotation=@hello.aop.member.annotation.ClassAop()
2023-03-29 20:27:26.213 INFO 34796 --- [ Test worker] h.a.p.ParameterTest$ParameterAspect : [@within]String hello.aop.member.MemberServiceImpl.hello(String), annotation=@hello.aop.member.annotation.ClassAop()
2023-03-29 20:27:26.213 INFO 34796 --- [ Test worker] h.a.p.ParameterTest$ParameterAspect : [logArgs3], arg=helloA
2023-03-29 20:27:26.213 INFO 34796 --- [ Test worker] h.a.p.ParameterTest$ParameterAspect : [targetArgs]String hello.aop.member.MemberServiceImpl.hello(String), obj=class hello.aop.member.MemberServiceImpl
2023-03-29 20:27:26.213 INFO 34796 --- [ Test worker] h.a.p.ParameterTest$ParameterAspect : [thisArgs]String hello.aop.member.MemberServiceImpl.hello(String), obj=class hello.aop.member.MemberServiceImpl$$EnhancerBySpringCGLIB$$62737d07
정리
- this : 프록시 객체를 전달 받는다
- target : 실제 대상 객체를 전달 받는다 (프록시 이전 오리지날 객체)
- @target, @within : 타입의 어노테이션을 전달 받는다.
- @Annotation : 메서드의 어노테이션을 전달 받는다. 여기서는 "annotation.getValue()"로 해당 값을 출력하는 결과를 확인 할 수있다.
반응형
'JAVA > AOP' 카테고리의 다른 글
[AOP] 실전예제 Service단 파라미터 Null체크 사용기 (1) | 2023.04.25 |
---|---|
[AOP] 실전예제 로그TRACE (0) | 2023.04.18 |
[AOP] this, target (0) | 2023.03.29 |
[AOP] @annotation (0) | 2023.03.23 |
[AOP] @target @within (0) | 2023.03.23 |