AOP(2) - Aop Proxy

Proxy๋ž€?

Proxy๋Š” ์‚ฌ์ „์ ์˜๋ฏธ๋กœ "๋Œ€๋ฆฌ์ธ"์ด๋ผ๋Š” ๋œป์ด๋‹ค. java์—์„œ์˜ ํ”„๋ก์‹œ๋Š” ๋Œ€๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ํด๋ž˜์Šค๋ผ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฆ‰, Proxy๋Š” Client๊ฐ€ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•˜๋Š” ์‹ค์ œ ๋Œ€์ƒ์ธ ๊ฒƒ์ฒ˜๋Ÿผ ์œ„์žฅ์„ ํ•ด์„œ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ๋ฐ›์•„์ค€๋‹ค. Proxy๋ฅผ ํ†ตํ•ด ์ตœ์ข…์ ์œผ๋กœ ์š”์ฒญ์„ ์œ„์ž„๋ฐ›์•„ ์ฒ˜๋ฆฌํ•˜๋Š” ์‹ค์ œ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ํƒ€๊ฒŸ(target) or ์‹ค์ฒด(real subject)๋ผ ๋ถ€๋ฅธ๋‹ค.

์‹ค์ œ ํƒ€๊ฒŸ์ด ๋‹ด๋‹นํ•˜๋Š” ์—ญํ•  ์š”์ฒญ์„ ๋Œ€์‹ ๋ฐ›์•„์„œ ์š”์ฒญ ์ด์ „, ์ดํ›„์— ๋Œ€ํ•œ ์ถ”๊ฐ€์ ์ธ ๋กœ์ง์„ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด์ด๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‹ค์ œ ํƒ€๊ฒŸ์ด ๋‹ด๋‹นํ•˜๋Š” ์—ญํ• ์— ๋Œ€ํ•ด์„œ ๊ด€์—ฌํ•˜์ง€ ์•Š์œผ๋ฉด์„œ ์ถ”๊ฐ€์ ์ธ ์—ญํ• ์„ ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

Proxy์˜ ํŠน์ง•

  1. target๊ณผ ๊ฐ™์€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„

  2. proxy๊ฐ€ target์„ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋Š” ์œ„์น˜์— ์žˆ๋‹ค.

AOP Proxy

https://t1.daumcdn.net/cfile/tistory/267BA1385510355B2E

์Šคํ”„๋ง์—์„œ ํ•จ์ˆ˜ ํ˜ธ์ถœ์ž๋Š” ์ฃผ์š” ์—…๋ฌด๊ฐ€ ์•„๋‹Œ ๋ณด์กฐ ์—…๋ฌด(๊ณตํ†ต๊ธฐ๋Šฅ)์€ ํ”„๋ก์‹œ์— ๋งก๊ธฐ๊ณ , ํ”„๋ก์‹œ๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ์ด๋Ÿฌํ•œ ๋ณด์กฐ์—…๋ฌด(๊ณตํ†ต ๊ธฐ๋Šฅ)์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.

ํ”„๋ก์‹œ์˜ ํ˜ธ์ถœ ๋ฐ ์ฒ˜๋ฆฌ์ˆœ์„œ

  1. Proxy ํ˜ธ์ถœ

  2. ๋ณด์กฐ ์—…๋ฌด ์ฒ˜๋ฆฌ

  3. Proxy ์ฒ˜๋ฆฌ ํ•จ์ˆ˜๊ฐ€ ์‹ค์ œ ๊ตฌํ˜„ ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋ฐ ์ฃผ ์—…๋ฌด ์ฒ˜๋ฆฌ

  4. Proxyํ•จ์ˆ˜๊ฐ€ ๋‚˜๋จธ์ง€ ๋ณด์กฐ ์—…๋ฌด ์ฒ˜๋ฆฌ

  5. ์ฒ˜๋ฆฌ ์™„๋ฃŒ ํ›„, ํ˜ธ์ถœํ•จ์ˆ˜๋กœ ๋ฐ˜ํ™˜

์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด์„œ ์‚ดํŽด๋ณด์ž.

์˜ˆ๋ฅผ๋“ค์–ด, ๊ณ„์‚ฐ๊ธฐ๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ, ๊ฐ ํ•จ์ˆ˜๊ฐ€ ์ฒ˜๋ฆฌ๋˜๋Š” ์‹œ๊ฐ„์„ ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด?

public interface Calculator {

    public int add(int x, int y);
    public int subtract(int x, int y);
    public int multiply(int x, int y);
    public int divide(int x, int y);

}
public class myCalculator implements Calculator {
    @Override
    public int add(int x, int y) {
         // ๋ณด์กฐ ์—…๋ฌด (์‹œ๊ฐ„ ์ธก์ • ์‹œ์ž‘ & ๋กœ๊ทธ ์ถœ๋ ฅ)
        Log log = LogFactory.getLog(this.getClass());
        StopWatch sw = new StopWatch();
        sw.start();
        log.info(โ€œTimer Beginโ€);

        // ์ฃผ ์—…๋ฌด (๋ง์…ˆ ์—ฐ์‚ฐ)
               int sum = x + y; 

        // ๋ณด์กฐ ์—…๋ฌด (์‹œ๊ฐ„ ์ธก์ • ๋ & ์ธก์ • ์‹œ๊ฐ„ ๋กœ๊ทธ ์ถœ๋ ฅ)
        sw.stop();
        log.info(โ€œTimer Stop โ€“ Elapsed Time : โ€+ sw.getTotalTimeMillis());

        return sum;
    }

}

์—ฌ๊ธฐ์„œ ๋ณด์กฐ ์—…๋ฌด(์‹œ๊ฐ„ ์ธก์ •)์ด ๋‹ค๋ฅธ method์—์„œ๋„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด Proxy๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฆ‰, ์ฃผ์—…๋ฌด(์—ฐ์‚ฐ)๊ณผ ๋ณด์กฐ์—…๋ฌด(์‹œ๊ฐ„ ์ธก์ •)๋ฅผ ๋ถ„๋ฆฌ(Cross Cutting) ํ•˜๊ณ  ๋ณด์กฐ ์—…๋ฌด๋ฅผ Proxy๊ฐ€ ํ•˜๋ฉด๋œ๋‹ค.

// ๋ณด์กฐ ์—…๋ฌด๋ฅผ ์ฒ˜๋ฆฌํ•  ํ”„๋ก์‹œ ํด๋ž˜์Šค ์ •์˜
public class LogPrintHandler implements InvocationHandler { 

    private Object target; // ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ •๋ณด

    public LogPrintHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable   {

        Log log = LogFactory.getLog(this.getClass());
        StopWatch sw = new StopWatch();
        sw.start();
        log.info(โ€œTimer Beginโ€);

        int result = (int) method.invoke(target, args); // (3) ์ฃผ์—…๋ฌด๋ฅผ invoke ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ํ˜ธ์ถœ

        sw.stop();
        log.info(โ€œTimer Stop โ€“ Elapsed Time : โ€+ sw.getTotalTimeMillis());

        return result;
  }
}

InvocationHandler ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ๊ฐ์ฒด๋Š” invoke ๋ฉ”์†Œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด์•ผํ•œ๋‹ค. ํ•ด๋‹น ๊ฐ์ฒด์— ์˜ํ•˜์—ฌ ์š”์ฒญ ๋ฐ›์€ ๋ฉ”์†Œ๋“œ๋ฅผ reflection api๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‹ค์ œ ํƒ€๊ฒŸ์ด ๋˜๋Š” ๊ฐ์ฒด์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์ค€๋‹ค.

public static void main(String[] args) {

    Calculator cal = new myCalculator();

    //(1) ์‹ค์ œ ๊ฐ์ฒด๋ฅผ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ†ตํ•ด์„œ ์ „๋‹ฌ
    Calculator proxy_cal = (Calculator) Proxy.newProxyInstance( 
        cal.getClass().getClassLoader(),
        cal.getClass().getInterfaces(), 
        new LogPrintHandler(cal));

    System.out.println(proxy_cal.add(3, 4));    // (2) ์ฃผ ์—…๋ฌด ์ฒ˜๋ฆฌ ํด๋ž˜์Šค์˜ add ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœ
}
Calculator proxy_cal = (Calculator) Proxy.newProxyInstance( 
            // ๋™์ ์œผ๋กœ ์ƒ์„ฑ๋˜๋Š” DynamicProxy ํด๋ž˜์Šค์˜ ๋กœ๋”ฉ์— ์‚ฌ์šฉํ•  ํด๋ž˜์Šค ๋กœ๋”
                cal.getClass().getClassLoader(),
            // ๊ตฌํ˜„ํ•  ์ธ์Šคํ„ด์Šค
                cal.getClass().getInterfaces(), 
            // ๋ถ€๊ฐ€๊ธฐ๋Šฅ๊ณผ ์œ„์ž„ ์ฝ”๋“œ๋ฅผ ๋‹ด์€ ํ•ธ๋“ค๋Ÿฌ
                new LogPrintHandler(cal));
  1. mainํ•จ์ˆ˜์—์„œ ์‹ค์ œ ๊ฐ์ฒด๋ฅผ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ†ตํ•ด์„œ ์ „๋‹ฌํ•ด์ค€๋‹ค.

  2. ์ฃผ ์—…๋ฌด ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋˜๋ฉด ํ”„๋ก์‹œ ํด๋ž˜์Šค(LogPrintHandler)์˜ invoke ๋ฉ”์†Œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜์–ด ์ž์‹ ์˜ ๋ณด์กฐ ์—…๋ฌด๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ , ์ฃผ ์—…๋ฌด์˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

  3. invoke()๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰์‹œํ‚ฌ ๋Œ€์ƒ ๊ฐ์ฒด์™€ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ชฉ๋ก์„ ๋ฐ›์•„ ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๋’ค์— ๊ทธ ๊ฒฐ๊ณผ๋ฅผ Object ํƒ€์ž…์œผ๋กœ ๋Œ๋ ค์ค€๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด AOP๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” Proxy์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‹จ์ ์ด ์žˆ๋‹ค.

  1. ๋งค๋ฒˆ ์ƒˆ๋กœ์šด ํด๋ž˜์Šค ์ •์˜๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

    • ์‹ค์ œ ํ”„๋ก์‹œ ํด๋ž˜์Šค๋Š” ์‹ค์ œ ๊ตฌํ˜„ ํด๋ž˜์Šค์™€ ๋™์ผํ•œ ํ˜•ํƒœ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฏ€๋กœ, ๊ตฌํ˜„ ํด๋ž˜์Šค์˜ Interface๋ฅผ ๋ชจ๋‘ ๊ตฌํ˜„ํ•ด์•ผํ•œ๋‹ค.

  2. ํƒ€๊ฒŸ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์œ„์ž„ํ•˜๋Š” ์ฝ”๋“œ ์ž‘์„ฑ

    • ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์ด ํ•„์š”์—†๋Š” ๋ฉ”์†Œ๋“œ๋„ ๊ตฌํ˜„ํ•˜์—ฌ ํƒ€๊ฒŸ์œผ๋กœ ์œ„์ž„ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ผ์ผ์ด ๋งŒ๋“ค์–ด์ค˜์•ผํ•œ๋‹ค.

    • ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ฉ”์†Œ๋“œ๊ฐ€ ๋งŽ์•„์ง€๊ณ  ๋‹ค์–‘ํ•ด์ง€๋ฉด ๋ถ€๋‹ด์Šค๋Ÿฌ์šด ์ž‘์—…์ด ๋  ์ˆ˜ ์žˆ๋‹ค.

    • ํƒ€๊ฒŸ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ฉ”์†Œ๋“œ๊ฐ€ ์ถ”๊ฐ€๋˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ํ•จ๊ป˜ ์ˆ˜์ •ํ•ด์ค˜์•ผํ•œ๋‹ค.

  3. ๋ถ€๊ฐ€๊ธฐ๋Šฅ ์ฝ”๋“œ์˜ ์ค‘๋ณต ๊ฐ€๋Šฅ์„ฑ

    • ํ”„๋ก์‹œ๋ฅผ ํ™œ์šฉํ•˜๋Š” ๋ถ€๊ฐ€๊ธฐ๋Šฅ, ์ ‘๊ทผ์ œ์–ด ๊ธฐ๋Šฅ ๋“ฑ์€ ์ผ๋ฐ˜์ ์œผ๋กœ ์ž์ฃผ ํ™œ์šฉ๋˜๋Š” ๊ฒƒ์ด ๋งŽ๋‹ค. ์ฆ‰, ๋‹ค์–‘ํ•œ ํƒ€๊ฒŸ ํด๋ž˜์Šค์™€ ๋ฉ”์†Œ๋“œ์— ์ค‘๋ณต๋˜์–ด ๋‚˜ํƒ€๋‚  ๊ฐ€๋Šฅ์„ฑ์ด ๋งŽ๋‹ค.(ex) Transaction

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Dynamic Proxy๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉด๋œ๋‹ค.

์ฐธ์กฐ ํŽ˜์ด์ง€

Last updated

Was this helpful?