🌱Spring AOP

Dohyeon KongΒ·2023λ…„ 10μ›” 30일
0

Spring🌱

λͺ©λ‘ 보기
3/11
post-thumbnail

AOPπŸ‘€

AOPλž€? 관점 지ν–₯ ν”„λ‘œκ·Έλž˜λ°(Aspect Oriented Programming)의 μ•½μ–΄λ‘œ 'κ΅¬ν˜„ν•˜κ³  싢은 ν”„λ‘œκ·Έλž¨ = 쀑심적 관심사', 'λΆ€μˆ˜μ  ν”„λ‘œκ·Έλž¨ = νš‘λ‹¨μ  관심사'둜 λΆ„λ¦¬ν•˜μ—¬ ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜λŠ” 방식을 μ˜λ―Έν•œλ‹€.

μ—¬κΈ°μ„œ 관점(Aspect)λž€?

μ–΄λ–€ κΈ°λŠ₯을 κ΅¬ν˜„ν•  λ•Œ κ·Έ κΈ°λŠ₯을 '핡심 κΈ°λŠ₯'κ³Ό 'λΆ€κ°€ κΈ°λŠ₯'으둜 ꡬ뢀해 각각을 ν•˜λ‚˜μ˜ κ΄€μ μœΌλ‘œ λ³΄λŠ” 것을 μ˜λ―Έν•œλ‹€.

  • 핡심 κΈ°λŠ₯ : λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ κ΅¬ν˜„ν•˜λŠ” 과정을 λΉ„μ¦ˆλ‹ˆμŠ€ 둜직이 μ²˜λ¦¬ν•˜λ €λŠ” λͺ©μ μ˜ κΈ°λŠ₯을 μ˜λ―Έν•œλ‹€.
  • λΆ€κ°€ κΈ°λŠ₯ : λ‘œκΉ…μ²˜λ¦¬ ν˜Ήμ€ νŠΈλžœμž­μ…˜μ„ μ²˜λ¦¬ν•˜λŠ” κΈ°λŠ₯을 μ˜λ―Έν•˜λ©° 예λ₯Ό λ“€μ–΄ μœ μ§€λ³΄μˆ˜ λͺ©μ μ΄λ‚˜ λ°μ΄ν„°λ² μ΄μŠ€ 접근을 μœ„ν•΄

μ—¬λŸ¬ λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ— λ°˜λ³΅λ˜λŠ” λΆ€κ°€ κΈ°λŠ₯을 ν•˜λ‚˜μ˜ 곡톡 둜직으둜 μ²˜λ¦¬ν•˜λ„λ‘ λͺ¨λ“ˆν™”ν•΄ μ‚½μž…ν•˜λŠ” 방식 => AOP


AOP의 고유 μš©μ–΄

μš©μ–΄λ‚΄μš©
Advice(μ–΄λ“œλ°”μ΄μŠ€)νš‘λ‹¨μ  κ΄€μ‹¬μ‚¬μ˜ κ΅¬ν˜„(λ©”μ„œλ“œ)λ₯Ό μ˜λ―Έν•œλ‹€. 둜그 좜λ ₯ 및 νŠΈλžœμž­μ…˜ μ œμ–΄ λ“±μ˜ κΈ°λŠ₯을 μ˜λ―Έν•œλ‹€.
Aspect(μ• μŠ€νŽ™νŠΈ)μ–΄λ“œλ°”μ΄μŠ€λ₯Ό μ •λ¦¬ν•œ 것(클래슀)λ₯Ό μ˜λ―Έν•œλ‹€.
JoinPoint(쑰인포인트)μ–΄λ“œλ°”μ΄μŠ€λ₯Ό 쀑심적은 관심사에 μ μš©ν•˜λŠ” 타이밍을 μ˜λ―Έν•œλ‹€. λ©”μ„œλ“œ(μƒμ„±μž) μ‹€ν–‰ μ „, λ©”μ„œλ“œ(μƒμ„±μž) μ‹€ν–‰ ν›„ λ“± μ‹€ν–‰λ˜λŠ” 타이밍이닀.
Pointcut(포인트컷)μ–΄λ“œλ°”μ΄μŠ€λ₯Ό μ‚½μž…ν•  수 μžˆλŠ” μœ„μΉ˜λ₯Ό μ˜λ―Έν•œλ‹€. 예λ₯Ό λ“€μ–΄ λ©”μ„œλ“œ 이름이 get으둜 μ‹œμž‘ν•  λ•Œλ§Œ μ²˜λ¦¬ν•˜λŠ” 쑰건을 μ •μ˜ν•  수 μžˆλ‹€.
Interceptor(인터셉터)처리의 μ œμ–΄λ₯Ό μΈν„°μ…‰νŠΈν•˜κΈ° μœ„ν•œ ꡬ쑰 λ˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μ˜λ―Έν•œλ‹€. μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬μ—μ„œ μΈν„°μ…‰νŠΈλΌλŠ” λ©”μ»€λ‹ˆμ¦˜μœΌλ‘œ μ–΄λ“œλ°”μ΄μŠ€λ₯Ό 쀑심적 관심사에 μΆ”κ°€ν•œ κ²ƒμ²˜λŸΌ 보이게 ν•œλ‹€.
Target(νƒ€κ²Ÿ)μ–΄λ“œλ°”μ΄μŠ€κ°€ λ„μž…λ˜λŠ” λŒ€μƒμ„ μ˜λ―Έν•œλ‹€.

μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬μ—μ„œλŠ” '인터셉터'λΌλŠ” λ©”μ»€λ‹ˆμ¦˜μ„ μ‚¬μš©ν•˜μ—¬ νš‘λ‹¨μ  관심사(μ–΄λ“œλ°”μ΄μŠ€)λ₯Ό 쀑심적 관심사(타깃)에 μ‚½μž…ν•˜λŠ” κ²ƒμ²˜λŸΌ 보일 수 μžˆλ‹€.

μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬κ°€ μ œκ³΅ν•˜λŠ” 쀑심적 관심사에 μ μš©ν•˜λŠ” μ–΄λ“œλ°”μ΄μŠ€λŠ” μ‹€ν–‰ μ œμ–΄ λ‚΄μš©λ³„λ‘œ λ‹€μŒκ³Ό 같이 닀섯가지 μ’…λ₯˜κ°€ μžˆλ‹€.

Advice(μ–΄λ“œλ°”μ΄μŠ€)의 λ‹€μ„― 가지 μ’…λ₯˜

μ–΄λ“œλ°”μ΄μŠ€λ‚΄μš©μ–΄λ…Έν…Œμ΄μ…˜
Before Advice쀑심적 관심사가 μ‹€ν–‰λ˜κΈ° '이전'에 νš‘λ‹¨μ  관심사λ₯Ό μ‹€ν–‰ν•œλ‹€.@Before
After Returning Advice쀑심적 관심사가 'μ •μƒμ μœΌλ‘œ μ’…λ£Œλœ ν›„'에 νš‘λ‹¨μ  관심사λ₯Ό μ‹€ν–‰ν•œλ‹€.@AfterReturning
After Throwing Advice쀑심적 관심사가 'μ˜ˆμ™Έκ°€ λ˜μ Έμ§„ ν›„'둜 νš‘λ‹¨μ  관심사λ₯Ό μ‹€ν–‰ν•œλ‹€.@AfterThrowing
After Advice쀑심적 κ΄€μ‹¬μ‚¬μ˜ 'μ‹€ν–‰ ν›„'에 νš‘λ‹¨μ  관심사λ₯Ό μ‹€ν–‰ν•œλ‹€.
(정상 μ’…λ£Œλ‚˜ μ˜ˆμ™Έ μ’…λ£Œ λ“±μ˜ 결과와 상관없이 μ‹€ν–‰)
@After
Around Advice쀑심적 관심사 호좜 μ „, 후에 νš‘λ‹¨μ  관심사λ₯Ό μ‹€ν–‰ν•œλ‹€.@Around

Pointcut 식

직접 μ–΄λ“œλ°”μ΄μŠ€λ₯Ό λ§Œλ“œλŠ” 경우 νŒ¨ν‚€μ§€, 클래슀, λ©”μ„œλ“œ λ“± μ–΄λ“œλ°”μ΄μŠ€ μ‚½μž… λŒ€μƒμ„ 쑰건으둜 지정할 수 μžˆλ‹€. μ§€μ •ν•˜λŠ” 쑰건 λ°©λ²•μ—λŠ” 포인트컷 식을 μ‚¬μš©ν•œλ‹€. λ§Žμ€ 포인트컷 ν‘œν˜„μ‹ 쀑 execution μ§€μ‹œμžμ— λŒ€ν•΄ μ„€λͺ…ν•˜κ² λ‹€!

Pointcut 식 : execution(λ°˜ν™˜κ°’ νŒ¨ν‚€μ§€.클래슀.λ©”μ„œλ“œ(인수))

포인트컷 식은 μ™€μΌλ“œ μΉ΄λ“œλ₯Ό μ΄μš©ν•˜μ—¬ μœ μ—°ν•˜κ²Œ 적용 λ²”μœ„λ₯Ό 지정할 수 μžˆλ‹€.

μ™€μΌλ“œμΉ΄λ“œ

μ™€μΌλ“œμΉ΄λ“œλ‚΄μš©
* (μ• μŠ€ν„°λ¦¬μŠ€ν¬)μž„μ˜μ˜ λ¬Έμžμ—΄μ„ λ‚˜νƒ€λ‚΄κ³ , νŒ¨ν‚€μ§€λ₯Ό λ‚˜νƒ€λ‚Ό λ•ŒλŠ” μž„μ˜μ˜ νŒ¨ν‚€μ§€ ν•œ 계측을 λ‚˜νƒ€λ‚Έλ‹€. λ©”μ„œλ“œμ˜ μΈμˆ˜μ—μ„œλŠ” ν•œ 개의 인수λ₯Ό λ‚˜νƒ€λ‚΄ λ°˜ν™˜κ°’μœΌλ‘œλ„ μ΄μš©ν•œλ‹€.
.. (점 λ‘κ°œ)νŒ¨ν‚€μ§€λ₯Ό λ‚˜νƒ€λ‚΄λŠ” 경우 0개 μ΄μƒμ˜ νŒ¨ν‚€μ§€λ₯Ό λ‚˜νƒ€λ‚Έλ‹€. λ©”μ„œλ“œμ˜ 인수λ₯Ό ν‘œν˜„ν•˜λŠ” κ²½μš°μ—λŠ” 0개 μ΄μƒμ˜ μž„μ˜μ˜ 인수λ₯Ό λ‚˜νƒ€λ‚Έλ‹€.
+ (ν”ŒλŸ¬μŠ€)클래슀λͺ… 뒀에 κΈ°μˆ ν•΄ ν΄λž˜μŠ€μ™€ κ·Έ μ„œλΈŒν΄λž˜μŠ€ 및 κ΅¬ν˜„ 클래슀 λͺ¨λ‘λ₯Ό λ‚˜νƒ€λ‚Έλ‹€.

execution μ§€μ‹œμžμ˜ κ΅¬ν˜„ 예

κ΅¬ν˜„ μ˜ˆλ‚΄μš©
execution(* com.example.service.DemoService.*(..))DemoService 클래슀의 λ©”μ„œλ“œμ— μ–΄λ“œλ°”μ΄μŠ€λ₯Ό μ μš©ν•œλ‹€.
execution(* com.example.service.DemoService.select*(..))DemoService 클래슀의 select둜 μ‹œμž‘ν•˜λŠ” λ©”μ„œλ“œμ— μ–΄λ“œλ°”μ΄μŠ€λ₯Ό μ μš©ν•œλ‹€.
execution(String com.example.service.DemoService.*(..))DemoService 클래슀의 λ°˜ν™˜κ°’μ΄ String νƒ€μž…μΈ λ©”μ„œλ“œμ— μ–΄λ“œλ°”μ΄μŠ€λ₯Ό μ μš©ν•œλ‹€.
execution(* com.example.service.DemoService.*(String, ..))DemoService 클래슀의 첫 번째 μΈμˆ˜κ°€ String νƒ€μž…μΈ λ©”μ„œλ“œμ— μ–΄λ“œλ°”μ΄μŠ€λ₯Ό μ μš©ν•œλ‹€.
execution(* com.example.service..*.*(..))service νŒ¨ν‚€μ§€ λ°”λ‘œ μ•„λž˜μ™€ ν•˜μœ„ νŒ¨ν‚€μ§€μ™€ λͺ¨λ“  ν΄λž˜μŠ€μ— μ–΄λ“œλ°”μ΄μŠ€λ₯Ό μ μš©ν•œλ‹€.
execution(* com.example.service.DemoService.*(*))DemoService 클래슀의 μΈμˆ˜κ°€ ν•˜λ‚˜μΈ λ©”μ„œλ“œμ— μ–΄λ“œλ°”μ΄μŠ€λ₯Ό μ μš©ν•œλ‹€.

AOP 클래슀 μž‘μ„±

μ–΄λ“œλ°”μ΄μŠ€λ₯Ό κΈ°μˆ ν•˜λŠ” ν΄λž˜μŠ€λŠ” @Aspect μ–΄λ…Έν…Œμ΄μ…˜μ„ λΆ€μ—¬ν•œλ‹€.
그리고 μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜κΈ° μœ„ν•΄ @Component μ–΄λ…Έν…Œμ΄μ…˜μ„ λΆ€μ—¬ν•œλ‹€.

클래슀 μ•ˆμ— Advice λ©”μ„œλ“œλ₯Ό μž‘μ„±ν•˜κ³  λ©”μ„œλ“œ μΈμˆ˜λ‘œλŠ” JoinPointλ₯Ό μ „λ‹¬ν•œλ‹€.

//λŒ€ν‘œμ μΈ 예
@Before("execution(* com.example.demo.chater03.used.*Greet.*(..))")
public void beforeAdvice(JoinPoint joinpoint){
	//μ‹œμž‘ λΆ€λΆ„ ν‘œμ‹œ
    System.out.println("====Before Advice===="
    //λ‚ μ§œ 좜λ ₯
    SYstem.out.println(new SimpleDateFormat("yyyy/MM/dd").format(new java.util.Date()));
    //λ©”μ„œλ“œ 이름 좜λ ₯
    System.out.println(String.format("λ©”μ„œλ“œ : %s, joinPoint.getSignature().getName()));
}

//좜λ ₯ κ²°κ³Ό
====Before Advice====
2023/10/30
λ©”μ„œλ“œ : greeting
---------------------
쒋은 μ €λ…μž…λ‹ˆλ‹€.
---------------------

ν•΄λ‹Ή μ˜ˆμ‹œλ₯Ό ν•΄μ„ν•œλ‹€λ©΄ com.example.demo.chapter03.usedμ—μ„œ 클래슀 이름이 Greet둜 λλ‚˜λŠ” 클래슀의 λͺ¨λ“  λ©”μ„œλ“œμ— λŒ€ν•΄ 'λ‚ μ§œμ™€ λ©”μ„œλ“œ 이름을 ν‘œμ‹œν•˜λŠ” μ–΄λ“œλ°”μ΄μŠ€'λ₯Ό μž‘μ„±ν•œ ν›„ μ‹€ν–‰ν•œ 결과이닀.

Around Adviceλ₯Ό μ œμ™Έν•œ 거의 λͺ¨λ“  μ–΄λ“œλ°”μ΄μŠ€λŠ” μœ„μ— λ°©μ‹μœΌλ‘œ μ½”λ“œλ₯Ό μž‘μ„±ν•˜λ©΄ λœλ‹€.

+) Around Advice μž‘μ„±

//λŒ€ν‘œμ μΈ 예
@Around("execution(* com.example.demo.chater03.used.*Greet.*(..))")
public void aroundAdvice(ProceedingJoinPoint joinpoint) thorws Throwable{
	//μ‹œμž‘ λΆ€λΆ„ ν‘œμ‹œ
    System.out.println("====Around Advice===="
    System.out.println("β–Όβ–Ό μ²˜λ¦¬μ „ β–Όβ–Ό");
    //μ§€μ •ν•œ 클래슀의 λ©”μ„œλ“œ μ‹€ν–‰
    Object result = joinPoint.proceed();
    System.out.println("β–²β–² μ²˜λ¦¬ν›„ β–²β–²")
    //λ°˜ν™˜κ°’μ„ λŒλ €μ€„ ν•„μš”κ°€ μžˆλŠ” 경우 Object νƒ€μž…μ˜ λ°˜ν™˜κ°’μœΌλ‘œ λŒλ €μ€€λ‹€.
    return result;
}

//좜λ ₯ κ²°κ³Ό
====Around Advice====
β–Όβ–Ό μ²˜λ¦¬μ „ β–Όβ–Ό
---------------------
쒋은 μ €λ…μž…λ‹ˆλ‹€.
---------------------
β–²β–² μ²˜λ¦¬ν›„ β–²β–²"
---------------------

Arond Adviceκ°€ λ‹€λ₯Έ μ–΄λ“œλ°”μ΄μŠ€μ™€ λ‹€λ₯Έ 점🫒

  • μΈμˆ˜λŠ” ProceedingJoinPoint μΈν„°νŽ˜μ΄μŠ€ νƒ€μž…μ„ μ§€μ •ν•œλ‹€.
  • μ–΄λ“œλ°”μ΄μŠ€ 쀑 ProceedingJoinPoint μΈν„°νŽ˜μ΄μŠ€μ˜ proceed()λ₯Ό ν˜ΈμΆœν•œλ‹€.
  • μ–΄λ“œλ°”μ΄μŠ€ 적용 λŒ€μƒμ˜ λ©”μ„œλ“œλ₯Ό μž„μ˜μ˜ νƒ€μ΄λ°μœΌλ‘œ ν˜ΈμΆœν•  수 μžˆμœΌλ―€λ‘œ μ „ν›„λ‘œ λ‹€μ–‘ν•œ μ²˜λ¦¬κ°€ κ°€λŠ₯ν•˜λ‹€.
  • λ°˜ν™˜κ°’μ„ λŒλ €μ€„ ν•„μš”κ°€ μžˆλŠ” 경우 Object νƒ€μž…μœΌλ‘œ λ°˜ν™˜κ°’μ„ λŒλ €μ€€λ‹€.

ReferenceπŸ“š

  • μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬ 첫걸음 - ν›„λ£¨λ„€μŠ€ ν‚€λ…Έμ‹œνƒ€ λ§ˆμ‚¬μ•„ν‚€ -
  • μŠ€ν”„λ§λΆ€νŠΈ 핡심 κ°€μ΄λ“œ - μž₯μ •μš° -
profile
천천히, κΎΈμ€€νžˆ, 그리고 λκΉŒμ§€

0개의 λŒ“κΈ€