Spring/AOP

ํ”„๋ก์‹œ ํŒฉํ† ๋ฆฌ

an_jjin 2024. 11. 11. 19:53
๐Ÿ’ก ๊น€์˜ํ•œ๋‹˜์˜ ์Šคํ”„๋ง ํ•ต์‹ฌ ์›๋ฆฌ ๊ณ ๊ธ‰ํŽธ ๊ฐ•์˜๋ฅผ ๋“ฃ๊ณ  ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.

ํ”„๋ก์‹œ ํŒฉํ† ๋ฆฌ

๋™์  ํ”„๋ก์‹œ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๋ฌธ์ œ์ 

  • ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋Š” JDK ๋™์  ํ”„๋ก์‹œ๋ฅผ ์ ์šฉํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋Š” CGLIB๋ฅผ ์ ์šฉํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?
  • ๋‘ ๊ธฐ์ˆ ์„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ๋•Œ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด JDK ๋™์  ํ”„๋ก์‹œ๊ฐ€ ์ œ๊ณตํ•˜๋Š” InvocationHandler์™€ CGLIB๊ฐ€ ์ œ๊ณตํ•˜๋Š” MethodInterceptor๋ฅผ ๊ฐ๊ฐ ์ค‘๋ณต์œผ๋กœ ๋งŒ๋“ค์–ด์„œ ๊ด€๋ฆฌํ•ด์•ผ ํ• ๊นŒ?
  • ํŠน์ • ์กฐ๊ฑด์— ๋งž์„ ๋•Œ ํ”„๋ก์‹œ ๋กœ์ง์„ ์ ์šฉํ•˜๋Š” ๊ธฐ๋Šฅ๋„ ๊ณตํ†ต์œผ๋กœ ์ œ๊ณต๋˜์—ˆ์œผ๋ฉด?

Q: ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋Š” JDK ๋™์  ํ”„๋ก์‹œ๋ฅผ ์ ์šฉํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋Š” CGLIB๋ฅผ ์ ์šฉํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?

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

Q: ๋‘ ๊ธฐ์ˆ ์„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ๋•Œ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•ด JDK ๋™์  ํ”„๋ก์‹œ๊ฐ€ ์ œ๊ณตํ•˜๋Š” InvocationHandler์™€ CGLIB๊ฐ€ ์ œ๊ณตํ•˜๋Š” MethodInterceptor๋ฅผ ๊ฐ๊ฐ ์ค‘๋ณต์œผ๋กœ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด์•ผ ํ• ๊นŒ?

์Šคํ”„๋ง์€ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•  ๋•Œ Advice๋ผ๋Š” ์ƒˆ๋กœ์šด ๊ฐœ๋…์„ ๋„์ž…ํ–ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๋Š” InvocationHandler ๋‚˜ MethodInterceptor๋ฅผ ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š๊ณ , Advice๋งŒ ๋งŒ๋“ค๋ฉด ๋œ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ InvocationHandler๋‚˜ MethodInterceptor๋Š” Advice๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋œ๋‹ค. ํ”„๋ก์‹œ ํŒฉํ† ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Advice๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ „์šฉ InvocationHandler, MethodInterceptor๋ฅผ ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉํ•œ๋‹ค.

Q: ํŠน์ • ์กฐ๊ฑด์— ๋งž์„ ๋•Œ ํ”„๋ก์‹œ ๋กœ์ง์„ ์ ์šฉํ•˜๋Š” ๊ธฐ๋Šฅ๋„ ๊ณตํ†ต์œผ๋กœ ์ œ๊ณต๋˜์—ˆ์œผ๋ฉด?

์•ž์„œ ํŠน์ • ๋ฉ”์„œ๋“œ ์ด๋ฆ„์˜ ์กฐ๊ฑด์— ๋งž์„ ๋•Œ๋งŒ ํ”„๋ก์‹œ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์ด ์ ์šฉ๋˜๋Š” ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ๋งŒ๋“ค์—ˆ๋‹ค.

์Šคํ”„๋ง์€ Pointcut์ด๋ผ๋Š” ๊ฐœ๋…์„ ๋„์ž…ํ•ด์„œ ์ด ๋ฌธ์ œ๋ฅผ ์ผ๊ด€์„ฑ ์žˆ๊ฒŒ ํ•ด๊ฒฐํ•œ๋‹ค.

์˜ˆ) save, delete ๋ถ€๋ถ„์—๋งŒ ๋กœ๊ทธ๋ฅผ ์ฐ๊ณ  ๋‚˜๋จธ์ง€ ๊ธฐ๋Šฅ์€ ๋กœ๊ทธ๋ฅผ ์ฐ๊ณ  ์‹ถ์ง€ ์•Š์€ ๊ฒฝ์šฐ์— Pointcut ๊ฐœ๋…์œผ๋กœ ํ•ด๊ฒฐ

์ •๋ฆฌ

ํ”„๋ก์‹œ๋ฅผ ์ƒ์„ฑํ•˜๋Š”๊ฑด ProxyFactory๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ƒ์„ฑํ•˜๊ณ  ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ ๋กœ์ง์€ Advice์— ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.

๋‚˜๋จธ์ง€๋Š” ์Šคํ”„๋ง์ด ์•Œ์•„์„œ ๋‹ค ์ถ”์ƒํ™”ํ•ด์„œ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ค€๋‹ค. 

ํ”„๋ก์‹œ ํŒฉํ† ๋ฆฌ - ์ธํ„ฐํŽ˜์ด์Šค

Advice ๋งŒ๋“ค๊ธฐ

Advice๋Š” ํ”„๋ก์‹œ์— ์ ์šฉํ•˜๋Š” ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ ๋กœ์ง์ด๋‹ค. ์ด๊ฒƒ์€ JDK ๋™์  ํ”„๋ก์‹œ๊ฐ€ ์ œ๊ณตํ•˜๋Š” InvocationHandler์™€ CGLIB๊ฐ€ ์ œ๊ณตํ•˜๋Š” MethodInterceptor์˜ ๊ฐœ๋…๊ณผ ์œ ์‚ฌํ•œ๋‹ค. ๋‘˜์„ ๊ฐœ๋…์ ์œผ๋กœ ์ถ”์ƒํ™” ํ•œ ๊ฒƒ์ด๋‹ค. ํ”„๋ก์‹œ ํŒฉํ† ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‘˜ ๋Œ€์‹ ์— Advice๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

 package org.aopalliance.intercept;
 public interface MethodInterceptor extends Interceptor {
     Object invoke(MethodInvocation invocation) throws Throwable;
}

MethodInvocation invocation ๋‚ด๋ถ€์—๋Š” ๋‹ค์Œ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ๋ฒ•, ํ˜„์žฌ ํ”„๋ก์‹œ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค, args, ๋ฉ”์„œ๋“œ ์ •๋ณด ๋“ฑ์ด ํฌํ•จ๋˜์–ด ์žˆ ๋‹ค. ๊ธฐ์กด์— ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ œ๊ณต๋˜๋Š” ๋ถ€๋ถ„๋“ค์ด ์ด ์•ˆ์œผ๋กœ ๋ชจ๋‘ ๋“ค์–ด๊ฐ”๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค. MethodInterceptor๋Š” Interceptor๋ฅผ ์ƒ์†ํ•˜๊ณ  Interceptor๋Š” Advice ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์†ํ•œ๋‹ค.

TimeAdvice

@Slf4j
public class TimeAdvice implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        log.info("TimeProxy ์‹คํ–‰");
        long startTime = System.currentTimeMillis();

        Object result = invocation.proceed();

        long endTime = System.currentTimeMillis();
        long resultTime = endTime - startTime;
        log.info("TimeProxy ์ข…๋ฃŒ resultTime={}", resultTime);
        return result;
    }
}

Object result = invocation.proceed()

invocation.proceed()๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์‹ค์ œ ๊ธฐ๋Šฅ์„ ๋‹ด๊ณ  ์žˆ๋Š” target ํด๋ž˜์Šค๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›๋Š”๋‹ค.

ProxyFactoryTest

@Slf4j
public class ProxyFactoryTest {

    @Test
    @DisplayName("์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์žˆ์œผ๋ฉด JDK ๋™์  ํ”„๋ก์‹œ ์‚ฌ์šฉ")
    void interfaceProxy() {
        ServiceInterface target = new ServiceImpl();
        ProxyFactory proxyFactory = new ProxyFactory(target);
        proxyFactory.addAdvice(new TimeAdvice());
        ServiceInterface proxy = (ServiceInterface) proxyFactory.getProxy();
        log.info("targetClass={}", target.getClass());
        log.info("proxyClass={}", proxy.getClass());

        proxy.save();

        assertThat(AopUtils.isAopProxy(proxy)).isTrue();
        assertThat(AopUtils.isJdkDynamicProxy(proxy)).isTrue();
        assertThat(AopUtils.isCglibProxy(proxy)).isFalse();
    }
}

new ProxyFactory(target)

ํ”„๋ก์‹œ ํŒฉํ† ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ, ์ƒ์„ฑ์ž์— ํ”„๋ก์‹œ์˜ ํ˜ธ์ถœ ๋Œ€์ƒ์„ ํ•จ๊ป˜ ๋„˜๊ฒจ์ค€๋‹ค. ํ”„๋ก์‹œ ํŒฉํ† ๋ฆฌ๋Š” ์ด ์ธ์Šคํ„ด์Šค ์ •๋ณด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ”„๋ก์‹œ๋ฅผ ๋งŒ๋“ค์–ด๋‚ธ๋‹ค. ๋งŒ์•ฝ ์ด ์ธ์Šคํ„ด์Šค์— ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์žˆ๋‹ค๋ฉด JDK ๋™์  ํ”„๋ก์‹œ๋ฅผ ๊ธฐ๋ณธ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์—†๊ณ  ๊ตฌ์ฒด ํด๋ž˜์Šค๋งŒ ์žˆ๋‹ค๋ฉด CGLIB๋ฅผ ํ†ตํ•ด์„œ ๋™์  ํ”„๋ก์‹œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” target์ด new ServiceImpl()์˜ ์ธ์Šคํ„ด์Šค์ด๊ธฐ ๋•Œ๋ฌธ์— ServiceInterface ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ JDK ๋™์  ํ”„๋ก์‹œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

proxyFactory.addAdvice(new TimeAdvice())

ํ”„๋ก์‹œ ํŒฉํ† ๋ฆฌ๋ฅผ ํ†ตํ•ด์„œ ๋งŒ๋“  ํ”„๋ก์‹œ๊ฐ€ ์‚ฌ์šฉํ•  ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ ๋กœ์ง์„ ์„ค์ •ํ•œ๋‹ค.

JDK ๋™์  ํ”„๋ก์‹œ๊ฐ€ ์ œ๊ณตํ•˜๋Š” InvocationHandler์™€ CGLIB๊ฐ€ ์ œ๊ณตํ•˜๋Š” MethodInterceptor์˜ ๊ฐœ๋…๊ณผ ์œ ์‚ฌํ•˜๋‹ค.

์ด๋ ‡๊ฒŒ ํ”„๋ก์‹œ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ ๋กœ์ง์„ ์–ด๋“œ๋ฐ”์ด์Šค( Advice )๋ผ ํ•œ๋‹ค.

๋ฒˆ์—ญํ•˜๋ฉด ์กฐ์–ธ์„ ํ•ด์ค€๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.

proxyFactory.getProxy()

ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›๋Š”๋‹ค.

ํ”„๋ก์‹œ ํŒฉํ† ๋ฆฌ - ๊ตฌ์ฒด ํด๋ž˜์Šค

์ด๋ฒˆ์—๋Š” ๊ตฌ์ฒด ํด๋ž˜์Šค๋งŒ ์žˆ๋Š” ConcreteService์— ํ”„๋ก์‹œ๋ฅผ ์ ์šฉํ•ด๋ณด์ž.

ํ”„๋ก์‹œ ํŒฉํ† ๋ฆฌ๋Š” ์ธํ„ฐํŽ˜์ด์Šค ์—†์ด ๊ตฌ์ฒด ํด๋ž˜์Šค๋งŒ ์žˆ์œผ๋ฉด CGLIB๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ”„๋ก์‹œ๋ฅผ ์ ์šฉํ•œ๋‹ค.

@Test
@DisplayName("๊ตฌ์ฒด ํด๋ž˜์Šค๋งŒ ์žˆ์œผ๋ฉด CGLIB ์‚ฌ์šฉ")
void concreteProxy() {
    ConcreteService target = new ConcreteService();
    ProxyFactory proxyFactory = new ProxyFactory(target);
    proxyFactory.addAdvice(new TimeAdvice());
    ConcreteService proxy = (ConcreteService) proxyFactory.getProxy();
    log.info("targetClass={}", target.getClass());
    log.info("proxyClass={}", proxy.getClass());

    proxy.call();

    assertThat(AopUtils.isAopProxy(proxy)).isTrue();
    assertThat(AopUtils.isJdkDynamicProxy(proxy)).isFalse();
    assertThat(AopUtils.isCglibProxy(proxy)).isTrue();
}

proxyTargetClass ์˜ต์…˜

@Test
@DisplayName("ProxyTargetClass ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์žˆ์–ด๋„ CGLIB๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ํด๋ž˜์Šค ๊ธฐ๋ฐ˜ ํ”„๋ก์‹œ ์‚ฌ์šฉ")
void proxyTargetClass() {
    ServiceInterface target = new ServiceImpl();
    ProxyFactory proxyFactory = new ProxyFactory(target);
    proxyFactory.setProxyTargetClass(true);
    proxyFactory.addAdvice(new TimeAdvice());
    ServiceInterface proxy = (ServiceInterface) proxyFactory.getProxy();
    log.info("targetClass={}", target.getClass());
    log.info("proxyClass={}", proxy.getClass());

    proxy.save();

    assertThat(AopUtils.isAopProxy(proxy)).isTrue();
    assertThat(AopUtils.isJdkDynamicProxy(proxy)).isFalse();
    assertThat(AopUtils.isCglibProxy(proxy)).isTrue();
}

๋งˆ์ง€๋ง‰์œผ๋กœ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์žˆ์ง€๋งŒ, CGLIB๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์•„๋‹Œ ํด๋ž˜์Šค ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์  ํ”„๋ก์‹œ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์ž. ํ”„๋ก์‹œ ํŒฉํ† ๋ฆฌ๋Š” proxyTargetClass๋ผ๋Š” ์˜ต์…˜์„ ์ œ๊ณตํ•˜๋Š”๋ฐ, ์ด ์˜ต์…˜์— true ๊ฐ’์„ ๋„ฃ์œผ๋ฉด ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์žˆ์–ด๋„ ๊ฐ•์ œ๋กœ CGLIB๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์•„๋‹Œ ํด๋ž˜์Šค ๊ธฐ๋ฐ˜์˜ ํ”„๋ก์‹œ๋ฅผ ๋งŒ๋“ค์–ด์ค€๋‹ค.

ํ”„๋ก์‹œ ํŒฉํ† ๋ฆฌ์˜ ๊ธฐ์ˆ  ์„ ํƒ ๋ฐฉ๋ฒ•

  • ๋Œ€์ƒ์— ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์žˆ์œผ๋ฉด: JDK ๋™์  ํ”„๋ก์‹œ, ์ธํ„ฐํŽ˜์ด์Šค ๊ธฐ๋ฐ˜ ํ”„๋ก์‹œ
  • ๋Œ€์ƒ์— ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์—†์œผ๋ฉด: CGLIB, ๊ตฌ์ฒด ํด๋ž˜์Šค ๊ธฐ๋ฐ˜ ํ”„๋ก์‹œ
  • proxyTargetClass=true: CGLIB, ๊ตฌ์ฒด ํด๋ž˜์Šค ๊ธฐ๋ฐ˜ ํ”„๋ก์‹œ, ์ธํ„ฐํŽ˜์ด์Šค ์—ฌ๋ถ€์™€ ์ƒ๊ด€์—†์Œ

์ •๋ฆฌ

ํ”„๋ก์‹œ ํŒฉํ† ๋ฆฌ์˜ ์„œ๋น„์Šค ์ถ”์ƒํ™” ๋•๋ถ„์— ๊ตฌ์ฒด์ ์ธ CGLIB, JDK ๋™์  ํ”„๋ก์‹œ ๊ธฐ์ˆ ์— ์˜์กดํ•˜์ง€ ์•Š๊ณ , ๋งค์šฐ ํŽธ๋ฆฌํ•˜๊ฒŒ ๋™์  ํ”„๋ก์‹œ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. ํ”„๋ก์‹œ์˜ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ ๋กœ์ง๋„ ํŠน์ • ๊ธฐ์ˆ ์— ์ข…์†์ ์ด์ง€ ์•Š๊ฒŒ Advice ํ•˜๋‚˜๋กœ ํŽธ๋ฆฌํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์ด๊ฒƒ์€ ํ”„ ๋ก์‹œ ํŒฉํ† ๋ฆฌ๊ฐ€ ๋‚ด๋ถ€์—์„œ JDK ๋™์  ํ”„๋ก์‹œ์ธ ๊ฒฝ์šฐ InvocationHandler๊ฐ€ Advice๋ฅผ ํ˜ธ์ถœํ•˜๋„๋ก ๊ฐœ๋ฐœํ•ด๋‘๊ณ , CGLIB์ธ ๊ฒฝ์šฐ MethodInterceptor๊ฐ€ Advice๋ฅผ ํ˜ธ์ถœํ•˜๋„๋ก ๊ธฐ๋Šฅ์„ ๊ฐœ๋ฐœํ•ด๋‘์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ฐธ๊ณ 

์Šคํ”„๋ง ๋ถ€ํŠธ๋Š” AOP๋ฅผ ์ ์šฉํ•  ๋•Œ ๊ธฐ๋ณธ์ ์œผ๋กœ proxyTargetClass=true๋กœ ์„ค์ •ํ•ด์„œ ์‚ฌ์šฉํ•œ๋‹ค.

๋”ฐ๋ผ์„œ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์žˆ์–ด๋„ ํ•ญ์ƒ CGLIB๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ตฌ์ฒด ํด๋ž˜์Šค๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ”„๋ก์‹œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.