[Spring] AOP

지인·2023λ…„ 7μ›” 31일
0

Spring

λͺ©λ‘ 보기
18/20
post-custom-banner

🐰 AOP

Aspect Oriented Programming
🐾 ν”„λ‘œκ·Έλž¨ ꡬ쑰에 λŒ€ν•œ 또 λ‹€λ₯Έ 사고 방식을 μ œκ³΅ν•˜μ—¬ 객체 지ν–₯ ν”„λ‘œκ·Έλž˜λ°(OOP)을 보완
🐾 OOPμ—μ„œ λͺ¨λ“ˆν™”μ˜ 핡심 λ‹¨μœ„λŠ” 클래슀인 반면, AOPμ—μ„œ λͺ¨λ“ˆν™”μ˜ λ‹¨μœ„λŠ” 관점이닀.

  • Spring의 핡심 κ΅¬μ„±μš”μ†Œ 쀑 ν•˜λ‚˜λŠ” AOP ν”„λ ˆμž„μ›Œν¬μ΄λ‹€.

  • 관점 지ν–₯은 μ–΄λ–€ λ‘œμ§μ„ κΈ°μ€€μœΌλ‘œ 핡심적인 관점, 뢀가적인 κ΄€μ μœΌλ‘œ λ‚˜λˆ„μ–΄μ„œ 보고 κ·Έ 관점을 κΈ°μ€€μœΌλ‘œ 각각 λͺ¨λ“ˆν™”ν•˜κ² λ‹€λŠ” 것이닀.

    • λͺ¨λ“ˆν™” : μ–΄λ–€ κ³΅ν†΅λœ λ‘œμ§μ΄λ‚˜ κΈ°λŠ₯을 ν•˜λ‚˜μ˜ λ‹¨μœ„λ‘œ λ¬ΆλŠ” 것을 λ§ν•œλ‹€.
  • AOPμ—μ„œ 각 관점을 κΈ°μ€€μœΌλ‘œ λ‘œμ§μ„ λͺ¨λ“ˆν™”ν•œλ‹€λŠ” 것은 μ½”λ“œλ“€μ„ λΆ€λΆ„μ μœΌλ‘œ λ‚˜λˆ„μ–΄μ„œ λͺ¨λ“ˆν™”ν•˜κ² λ‹€λŠ” 의미. μ΄λ•Œ, μ†ŒμŠ€ μ½”λ“œμƒμ—μ„œ λ‹€λ₯Έ 뢀뢄에 계속 λ°˜λ³΅ν•΄μ„œ μ“°λŠ” μ½”λ“œλ“€μ„ λ°œκ²¬ν•  수 μžˆλŠ” 데 이것을 흩어진 관심사 (Crosscutting Concerns)라 λΆ€λ₯Έλ‹€.

  • μœ„μ™€ 같이 흩어진 관심사λ₯Ό Aspect둜 λͺ¨λ“ˆν™”ν•˜κ³  핡심적인 λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ—μ„œ λΆ„λ¦¬ν•˜μ—¬ μž¬μ‚¬μš©ν•˜κ² λ‹€λŠ” 것이 AOP의 취지닀.

핡심 κ°œλ… 및 μš©μ–΄

  • Aspect : μœ„μ—μ„œ μ„€λͺ…ν•œ 흩어진 관심사λ₯Ό λͺ¨λ“ˆν™” ν•œ 것. 주둜 λΆ€κ°€κΈ°λŠ₯을 λͺ¨λ“ˆν™”ν•œλ‹€.
@Aspect
/*
* Aspect ν΄λž˜μŠ€λŠ” 포인트컷(Pointcut)κ³Ό μ–΄λ“œλ°”μ΄μŠ€(Advice)둜 κ΅¬μ„±λœλ‹€.
* 포인트컷 (Pointcut) : μ–΄λ–€ λ©”μ„œλ“œκ°€ μ–΄λ“œλ°”μ΄μŠ€λ₯Ό μ μš©ν•  λŒ€μƒμΈμ§€λ₯Ό μ •μ˜.
*                    : νŠΉμ • λ©”μ„œλ“œ μ‹€ν–‰ μ‹œμ μ„ μ§€μ •ν•˜κΈ° μœ„ν•œ ν‘œν˜„μ‹μ΄λ‚˜ λ©”μ„œλ“œ νŒ¨ν„΄μ„ μ •μ˜ν•  수 μžˆλ‹€.
* μ–΄λ“œλ°”μ΄μŠ€ (Advice) : 포인트컷이 μ§€μ •ν•œ μ‹œμ μ— μ‹€ν–‰λ˜λŠ” λ‘œμ§μ„ μ •μ˜
*                   : λ©”μ„œλ“œ μ‹€ν–‰ μ „(before), ν›„(after), μ˜ˆμ™Έ λ°œμƒ μ‹œ(after-throwing),
*                     정상 μ’…λ£Œ μ‹œ(after-returning) 등에 싀행될 수 μžˆλ‹€.
*/
  • Join point : Adviceκ°€ 적용될 μœ„μΉ˜, 끼어듀 수 μžˆλŠ” 지점. λ©”μ„œλ“œ μ§„μž… 지점, μƒμ„±μž 호좜 μ‹œμ , ν•„λ“œμ—μ„œ 값을 κΊΌλ‚΄μ˜¬ λ•Œ λ“± λ‹€μ–‘ν•œ μ‹œμ μ— μ μš©κ°€λŠ₯ν•˜λ‹€. Spring AOPμ—μ„œ 쑰인 ν¬μΈνŠΈλŠ” 항상 λ©”μ†Œλ“œ 싀행을 λ‚˜νƒ€λ‚Έλ‹€.

  • Advice : μ‹€μ§ˆμ μœΌλ‘œ μ–΄λ–€ 일을 ν•΄μ•Όν•  지에 λŒ€ν•œ 것, μ‹€μ§ˆμ μΈ λΆ€κ°€κΈ°λŠ₯을 담은 κ΅¬ν˜„μ²΄
    νŠΉμ • 쑰인 ν¬μΈνŠΈμ—μ„œ aspect에 μ˜ν•΄ 취해진 쑰치. λ‹€μ–‘ν•œ μœ ν˜•μ˜ adviceμ—λŠ” "around", "before" 및 "after" adviceκ°€ ν¬ν•¨λœλ‹€.

  • PointCut : JointPoint의 μƒμ„Έν•œ μŠ€νŽ™μ„ μ •μ˜ν•œ 것. 'Aλž€ λ©”μ„œλ“œμ˜ μ§„μž… μ‹œμ μ— ν˜ΈμΆœν•  것'κ³Ό 같이 λ”μš± ꡬ체적으둜 Adviceκ°€ 싀행될 지점을 μ •ν•  수 있음
    AdviceλŠ” pointcut ν‘œν˜„μ‹κ³Ό μ—°κ΄€λ˜λ©° pointcutκ³Ό μΌμΉ˜ν•˜λŠ” λͺ¨λ“  쑰인 ν¬μΈνŠΈμ—μ„œ μ‹€ν–‰λœλ‹€.(예: νŠΉμ • μ΄λ¦„μ˜ λ©”μ†Œλ“œ μ‹€ν–‰)

    /*
    * execution(modifiers-pattern? return-type-pattern declaring-type-pattern? method-name-pattern(param-pattern) throws-pattern?)
    * execution(..) : λ©”μ„œλ“œ μ‹€ν–‰ μ‹œμ μ„ μ§€μ •ν•˜λŠ” ν‚€μ›Œλ“œ
    * modifiers-pattern : λ©”μ„œλ“œμ˜ μ ‘κ·Ό μ œμ–΄μžλ₯Ό 지정 ex) public, private, protected, * λ“±
    * return-type-pattern : λ©”μ„œλ“œμ˜ λ°˜ν™˜ νƒ€μž… 지정 ex) void, String, * λ“±
    * declaring-type-pattern : λ©”μ„œλ“œλ₯Ό μ„ μ–Έν•œ 클래슀의 νŒ¨ν‚€μ§€μ™€ 클래슀 이름을 지정 ex) com.sparta.spring_lv4.service.*
    * method-name-pattern : λ©”μ„œλ“œμ˜ 이름을 지정 ex) updatePost, * λ“±
    * param-pattern : λ©”μ„œλ“œμ˜ νŒŒλΌλ―Έν„° νƒ€μž…μ„ 지정 ex) (String, int) λ“± νŠΉμ • νŒŒλΌλ―Έν„°λ₯Ό μ§€μ •ν•˜κ±°λ‚˜ (..)와 같이 λͺ¨λ“  νŒŒλΌλ―Έν„°λ₯Ό 선택할 수 μžˆλ‹€.
    * throws-pattern : λ©”μ„œλ“œκ°€ 던질 수 μžˆλŠ” μ˜ˆμ™Έ νƒ€μž…μ„ 지정
    */

    @Pointcut("execution(* com.sparta.spring_lv4.service.PostService.updatePost(..))")
    /*
    * : λͺ¨λ“  λ°˜ν™˜ νƒ€μž…
    com.sparta.spring_lv4.service.PostService 클래슀의 updatePost λ©”μ„œλ“œλ₯Ό 지정
    (..) : λͺ¨λ“  νŒŒλΌλ―Έν„°λ₯Ό 의미. 즉, νŒŒλΌλ―Έν„° κ°œμˆ˜μ™€ νƒ€μž…μ— λŒ€ν•΄ μΌμΉ˜ν•˜λŠ” λͺ¨λ“  λ©”μ„œλ“œλ₯Ό 선택
    정리 : @Pointcut 은 com.sparta.spring_lv4.service.PostService 클래슀의 updatePost λ©”μ„œλ“œλ₯Ό μ‹€ν–‰ μ‹œμ μœΌλ‘œ μ§€μ •ν•˜λ©°,
          ν•΄λ‹Ή λ©”μ„œλ“œκ°€ 호좜될 λ•Œ μ–΄λ“œλ°”μ΄μŠ€λ₯Ό μ‹€ν–‰ν•˜κ²Œ λœλ‹€.
    */
  • Target object : Aspectλ₯Ό μ μš©ν•˜λŠ” κ³³ (클래슀, λ©”μ„œλ“œ .. ). "advised object"라고도 ν•œλ‹€.

advice

  • @Before : 쑰인 포인트 이전에 μ‹€ν–‰λ˜μ§€λ§Œ 쑰인 포인트둜 μ§„ν–‰ν•˜λŠ” μ‹€ν–‰ 흐름을 λ°©μ§€ν•˜λŠ” κΈ°λŠ₯이 μ—†λŠ” advice (μ˜ˆμ™Έκ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ” ν•œ)

  • @AfterReturning : 쑰인 ν¬μΈνŠΈκ°€ μ •μƒμ μœΌλ‘œ μ™„λ£Œλœ ν›„ μ‹€ν–‰ν•  advice (예 : λ©”μ„œλ“œκ°€ μ˜ˆμ™Έλ₯Ό throw ν•˜μ§€ μ•Šκ³  return λ˜λŠ” 경우)

  • @AfterThrowing : μ˜ˆμ™Έλ₯Ό throw ν•˜μ—¬ λ©”μ„œλ“œκ°€ μ’…λ£Œλ˜λŠ” 경우

  • @After : 쑰인 ν¬μΈνŠΈκ°€ μ’…λ£Œλ˜λŠ” μˆ˜λ‹¨(정상 λ˜λŠ” μ˜ˆμ™Έ λ°˜ν™˜)에 관계없이 μ‹€ν–‰ν•  advice

  • @Around : λ©”μ†Œλ“œ 호좜과 같은 쑰인 포인트λ₯Ό λ‘˜λŸ¬μ‹ΈλŠ” advice
    λ©”μ„œλ“œ 호좜 전후에 μ‚¬μš©μž μ •μ˜ λ™μž‘μ„ μˆ˜ν–‰ν•  수 μžˆλ‹€. λ˜ν•œ 자체 return 값을 λ°˜ν™˜ν•˜κ±°λ‚˜ μ˜ˆμ™Έλ₯Ό throwν•˜μ—¬ μ‘°μΈμ§€μ μœΌλ‘œ 진행할지 λ˜λŠ” ꢌμž₯된 λ©”μ„œλ“œ 싀행을 단좕할지 μ—¬λΆ€λ₯Ό 선택할 μ±…μž„μ΄ μžˆλ‹€.

@Aspect
@Component
public class MyAspect {

    @Before("execution(* com.example.service.MyService.doSomething(..))")
    public void beforeDoSomething() {
        // Before advice
        System.out.println("Before advice: doSomething λ©”μ„œλ“œ μ‹€ν–‰ 전에 μˆ˜ν–‰λ©λ‹ˆλ‹€.");
    }

    @AfterReturning("execution(* com.example.service.MyService.doSomething(..))")
    public void afterReturningDoSomething() {
        // After returning advice
        System.out.println("After returning advice: doSomething λ©”μ„œλ“œκ°€ μ •μƒμ μœΌλ‘œ μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.");
    }

    @AfterThrowing("execution(* com.example.service.MyService.doSomething(..))")
    public void afterThrowingDoSomething() {
        // After throwing advice
        System.out.println("After throwing advice: doSomething λ©”μ„œλ“œμ—μ„œ μ˜ˆμ™Έκ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.");
    }

    @After("execution(* com.example.service.MyService.doSomething(..))")
    public void afterDoSomething() {
        // After (finally) advice
        System.out.println("After advice: doSomething λ©”μ„œλ“œ μ‹€ν–‰ 후에 항상 μˆ˜ν–‰λ©λ‹ˆλ‹€.");
    }

    @Around("execution(* com.example.service.MyService.doSomething(..))")
    public Object aroundDoSomething(ProceedingJoinPoint joinPoint) throws Throwable {
        // Around advice - λ©”μ„œλ“œ 호좜 전에 μˆ˜ν–‰ν•  μž‘μ—…
        System.out.println("Around advice: doSomething λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜κΈ° 전에 μˆ˜ν–‰λ©λ‹ˆλ‹€.");
        
        // λ©”μ„œλ“œ 호좜
        Object result = joinPoint.proceed();
        
        // Around advice - λ©”μ„œλ“œ 호좜 후에 μˆ˜ν–‰ν•  μž‘μ—…
        System.out.println("Around advice: doSomething λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•œ 후에 μˆ˜ν–‰λ©λ‹ˆλ‹€.");
        
        return result;
    }
}


μ°Έκ³ 

Spring κ³΅μ‹λ¬Έμ„œ λ²ˆμ—­

[Spring] μŠ€ν”„λ§ AOP (Spring AOP) 총정리 : κ°œλ…, ν”„λ‘μ‹œ 기반 AOP, @AOP

profile
μ—΄μ©‘
post-custom-banner

0개의 λŒ“κΈ€