AOP(Aspected-Oriented Programming)

spring

07/08/2021





๐ŸŒฟ AOP(Aspected-Oriented Programming)

  • ์Šคํ”„๋ง๊ณผ ๋ณ„๊ฐœ๋กœ ๋ฐฉ๋ฒ•๋ก ์ž„
  • OOP๋Š” ์‚ฌ์šฉ์ž ๊ด€์ ์—์„œ์˜ ์ฃผ ์—…๋ฌด ๋กœ์ง์„ ์œ„์ฃผ๋กœ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ. ๋ฐ˜๋ฉด AOP ๋Š” ์ฃผ ์—…๋ฌด ๋กœ์ง์„ ๊ตฌํ˜„ํ•จ์— ์žˆ์–ด์„œ ๊ฐœ๋ฐœ์ž๋‚˜ ์šด์˜์ž ๋ฐ ๊ด€๋ฆฌ์ž๊ฐ€ ํ•„์š”์— ๋”ฐ๋ผ์„œ ์ฝ”๋“œ๋ฅผ ๋ผ์›Œ๋„ฃ๊ฒŒ ๋˜๋Š” ๋ถ€๊ฐ€์ ์ธ ๊ธฐ๋Šฅ(ex. ๋กœ๊ทธ์ฒ˜๋ฆฌ, ํŠธ๋ Œ์ ์…˜ ๋“ฑ...)์„ ๋ชจ๋“ˆํ™”ํ•˜๋Š” ๊ฒƒ.
  • ์ฆ‰, ์‚ฌ์šฉ์ž ๊ด€์ , ๊ฐœ๋ฐœ์ž ๊ด€์ , ์šด์˜์ž ๊ด€์ , ๋“ฑ๋“ฑ..์—ฌ๋Ÿฌ ๊ด€์ ๋“ค์„ ๊ณ ๋ คํ•ด์„œ ๋กœ์ง์„ ๋ถ„๋ฆฌํ•˜๊ณ  ๋ชจ๋“ˆํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•๋ก ์ด๊ธฐ ๋•Œ๋ฌธ์— Aspected ๊ด€์  ์ง€ํ–ฅ์  ํ”„๋กœ๊ทธ๋žจ์ด์ด๋ผ๊ณ  ํ•œ๋‹ค.

Concern - Primary(Core) Concern & Cross-cutting concern

spring-aop

  • primary(Core) Concern : ํ•ต์‹ฌ ๋กœ์ง
  • Cross-cutting Concern : ํ•ต์‹ฌ๋กœ์ง์„ ์œ„ ์•„๋ž˜๋กœ ๊ฐ์‹ธ๊ณ  ์žˆ๋Š” ๋ถ€๊ฐ€์ ์ธ ๊ณตํ†ต ๋กœ์ง


AOP ๊ตฌํ˜„ ๋ฐฉ์‹

  • ํ”„๋ก์‹œ๋กœ ์œ„์ž„๊ณผ ๋ถ€๊ฐ€์ž‘์—…์„ ํ†ตํ•ด AOP๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค.

spring-aop2



Proxy

1) ํ”„๋ก์‹œ๋ž€? ๊ธฐ์กด ์ฝ”๋“œ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๊ณ  ํƒ€๊นƒ์˜ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•˜๊ณ  ์ ‘๊ทผ๋ฐฉ๋ฒ•์„ ์ œ์–ดํ•˜๋Š” ๋ฐฉ๋ฒ•

2) ํ”„๋ก์‹œ์˜ ์—ญํ• 

  • ํƒ€๊ฒŸ์œผ๋กœ ์š”์ฒญ์„ ์œ„์ž„

  • ๋ถ€๊ฐ€๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰

  • ํ”„๋ก์‹œํŒฉํ† ๋ฆฌ์—๊ฒŒ ์ธํ„ฐํŽ˜์ด์Šค ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ด์ฃผ๋ฉด ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค์˜ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ž๋™์œผ๋กœ ๋งŒ๋“ค์–ด์ค€๋‹ค

  • ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ Proxy๋ฅผ ์ƒ์„ฑํ•ด์ฃผ๋Š” ๋ฐฉ์‹

  • ์ˆœ์ˆ˜ ์ž๋ฐ”๋กœ proxy ๋งŒ๋“ค๊ธฐ

    JAVA
    // ํƒ€๊นƒํด๋ž˜์Šค์˜ ์ธํ„ฐํŽ˜์ด์Šค
    package noums.aop.entity;
    public interface Exam {
    public int total();
    public float avg();
    }
    JAVA
    // ํƒ€๊นƒ ํด๋ž˜์Šค
    package noums.aop.entity;
    public class ExamImpl implements Exam {
    private int kor;
    private int eng;
    private int math;
    public ExamImpl() {
    // TODO Auto-generated constructor stub
    }
    public ExamImpl(int kor, int eng, int math) {
    this.kor = kor;
    this.eng = eng;
    this.math = math;
    }
    public int getKor() {
    return kor;
    }
    public void setKor(int kor) {
    this.kor = kor;
    }
    public int getEng() {
    return eng;
    }
    public void setEng(int eng) {
    this.eng = eng;
    }
    public int getMath() {
    return math;
    }
    public void setMath(int math) {
    this.math = math;
    }
    @Override
    public int total() {
    // ๋ถ€๊ฐ€๋กœ์ง
    // long start = System.currentTimeMillis();
    // ํ•ต์‹ฌ๋กœ์ง
    int result = kor+eng+math;
    // try {
    // Thread.sleep(200);
    // } catch (InterruptedException e) {
    // // TODO Auto-generated catch block
    // e.printStackTrace();
    // }
    //
    // // ๋ถ€๊ฐ€๋กœ์ง
    // long end = System.currentTimeMillis();
    //
    // String message = (end-start) + "ms ์‹œ๊ฐ„ ์†Œ์š” ";
    // System.out.println(message);
    return result;
    }
    @Override
    public float avg() {
    // ํ•ต์‹ฌ์—…๋ฌด
    float result = total() / 3.0f;
    return result;
    }
TEXT
}
```
```java
package noums.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import noums.aop.entity.Exam;
import noums.aop.entity.ExamImpl;
public class Project {
public static void main(String[] args) {
Exam exam = new ExamImpl(1,1,1); // ํƒ€๊นƒ์€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ์ ‘๊ทผํ•˜๋Š” ์Šต๊ด€์„ ๋“ค์ด์ž
//์ž๋ฐ”์—์„œ ์ œ๊ณต proxy
// loader : ์‹ค์ œ ๋กœ๋“œํ•  ๊ฐ์ฒด ,
// interfaces : ํ•ต์‹ฌ๋กœ์ง์ด ๊ตฌํ˜„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค. ํ•ต์‹ฌ๋กœ์ง์ด ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ ์žˆ์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐฐ์—ด๋กœ ์„ ์–ธํ•ด์ค€๋‹ค.
// h : ๋ถ€๊ฐ€๊ธฐ๋Šฅ์„ ๊ฝ‚์„ ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„
Exam proxyExam = (Exam) Proxy.newProxyInstance(Exam.class.getClassLoader(),
new Class[] {Exam.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// ๋ถ€๊ฐ€๊ธฐ๋Šฅ
long start = System.currentTimeMillis();
// ํ•ต์‹ฌ๊ธฐ๋Šฅ ํ˜ธ์ถœ
Object result = method.invoke(exam, args); // args : exam ์—์„œ ๊ตฌํ˜„ํ•˜๊ณ ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋“ค์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๊ฐ€์ ธ์˜ด
// ๋ถ€๊ฐ€๊ธฐ๋Šฅ
long end = System.currentTimeMillis();
String message = (end-start) + "ms ์‹œ๊ฐ„ ์†Œ์š” ";
System.out.println(message);
return result;
}
}
);
System.out.println("total is "+ proxyExam.avg());
}
}
```


์ถœ๋ ฅ

spring-aop3

TEXT
1. Exam์ธํ„ฐํŽ˜์ด์Šค ์ œ๊ณต
2. ํ”„๋ก์‹œํŒฉํ† ๋ฆฌ์—๊ฒŒ ๋‚˜์ด๋‚ดํ”ฝ ํ”„๋ก์‹œ ๋งŒ๋“ค์–ด๋‹ฌ๋ผ๊ณ  ์š”์ฒญ
3. Exam์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ชจ๋“  ๋ฉ”์†Œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•œ ์˜ค๋ธŒ์ ํŠธ ์ƒ์„ฑ
4. InvokationHandler ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ œ๊ณต โ†’ ๋‹ค์ด๋‚ด๋ฏน ํ”„๋ก์‹œ๊ฐ€ ๋ฐ›์€ ๋ชจ๋“  ์š”์ฒญ์„ InvokationHandler ์˜ invoke() ๋ฉ”์†Œ๋“œ๋กœ ๋ณด๋‚ด์คŒ.
5. Exam์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ฉ”์†Œ๋“œ๊ฐ€ ์•„๋ฌด๋ฆฌ ๋งŽ์•„๋„ invoke ๋ฉ”์†Œ๋“œ ํ•˜๋‚˜๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.


๐ŸŒฟ Spring AOP

์Šคํ”„๋ง์€ ํ”„๋ก์‹œ ๊ธฐ๋ฐ˜์˜ AOP ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค. ๋Ÿฐํƒ€์ž„ ์‹œ์ ์— ํƒ€๊ฒŸ ํด๋ž˜์Šค์— ๋Œ€ํ•œ ๋ถ€๊ฐ€๊ธฐ๋Šฅ์„ ์‹คํ–‰ํ•ด์ค„ ํ”„๋ก์‹œ ๋นˆ์„ ์ƒ์„ฑํ•ด์ค€๋‹ค. (์ž๋™ ํ”„๋ก์‹œ ์ƒ์„ฑ๊ธฐ)

์šฉ์–ด

  • Aspect : ๊ณตํ†ต์ฝ”๋“œ๋ฅผ ๋ชจ๋“ˆํ™” ํ•œ ๊ฒƒ

  • Target : Aspect ๊ฐ€ ์ ์šฉ๋˜๋Š” ๊ณณ

  • Advice : ์ˆœ์ˆ˜ํ•˜๊ฒŒ ๋ถ€๊ฐ€๊ธฐ๋Šฅ๋งŒ ์‹ค์ œ๋กœ ๊ตฌํ˜„๋œ ๋ถ€๋ถ„. ๋ถ€๊ฐ€๊ธฐ๋Šฅ ๊ตฌํ˜„์ฒด

    TEXT
    - Before
    - After returnning
    - After throwing : ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒ๋œ ํ›„ ๋™์ž‘
    - Around : ๋ฉ”์†Œ๋“œ์˜ ์‹คํ–‰ ์ž์ฒด๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Joint point : Advice ๊ฐ€ Target์— ์ ์šฉ๋˜๋Š” ์‹œ์ 

  • Point cut : Joint point ์˜ ์ƒ์„ธ์ŠคํŽ™์„ ์ •์˜ํ•œ ๊ฒƒ

    TEXT
    - execution(@execution) : ๋ฉ”์†Œ๋“œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ Pointcut์„ ์„ค์ •
    - within(@within) : ํŠน์ •ํ•œ ํƒ€์ž…(ํด๋ž˜์Šค)์„ ๊ธฐ์ค€์œผ๋กœ Pointcut์„ ์„ค์ •
    - this : ์ฃผ์–ด์ง„ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ๊ฐ์ฒด๋ฅผ ๋Œ€์ƒ์œผ๋กœ Pointcut์„ ์„ค์ •
    - args(@args) : ํŠน์ •ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ฐ€์ง€๋Š” ๋Œ€์ƒ๋“ค๋งŒ์„ PointCut์œผ๋กœ ์„ค์ •
    - @annotation : ํŠน์ •ํ•œ ์–ด๋…ธํ…Œ์ด์…˜์ด ์ ์šฉ๋œ ๋Œ€์ƒ๋“ค๋งŒ์„ Pointcut์œผ๋กœ ์„ค์ •




์ฐธ์กฐ

  • ์œ ํŠœ๋ธŒ newlecture ์Šคํ”„๋ง ๊ฐ•์˜
  • ํ† ๋น„์˜ ์Šคํ”„๋ง

WRITTEN BY

Keep It Simple, Stupid