Aspect Oriented Programming
πΎ νλ‘κ·Έλ¨ κ΅¬μ‘°μ λν λ λ€λ₯Έ μ¬κ³ λ°©μμ μ 곡νμ¬ κ°μ²΄ μ§ν₯ νλ‘κ·Έλλ°(OOP)μ 보μ
πΎ OOPμμ λͺ¨λνμ ν΅μ¬ λ¨μλ ν΄λμ€μΈ λ°λ©΄, AOPμμ λͺ¨λνμ λ¨μλκ΄μ
μ΄λ€.
Springμ ν΅μ¬ ꡬμ±μμ μ€ νλλ AOP νλ μμν¬μ΄λ€.
κ΄μ μ§ν₯μ μ΄λ€ λ‘μ§μ κΈ°μ€μΌλ‘ ν΅μ¬μ μΈ κ΄μ , λΆκ°μ μΈ κ΄μ μΌλ‘ λλμ΄μ λ³΄κ³ κ·Έ κ΄μ μ κΈ°μ€μΌλ‘ κ°κ° λͺ¨λννκ² λ€λ κ²μ΄λ€.
AOPμμ κ° κ΄μ μ κΈ°μ€μΌλ‘ λ‘μ§μ λͺ¨λννλ€λ κ²μ μ½λλ€μ λΆλΆμ μΌλ‘ λλμ΄μ λͺ¨λννκ² λ€λ μλ―Έ. μ΄λ, μμ€ μ½λμμμ λ€λ₯Έ λΆλΆμ κ³μ λ°λ³΅ν΄μ μ°λ μ½λλ€μ λ°κ²¬ν μ μλ λ° μ΄κ²μ ν©μ΄μ§ κ΄μ¬μ¬ (Crosscutting Concerns)λΌ λΆλ₯Έλ€.
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"λΌκ³ λ νλ€.@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] μ€νλ§ AOP (Spring AOP) μ΄μ 리 : κ°λ , νλ‘μ κΈ°λ° AOP, @AOP