AOP(Aspect-Oriented Programming)

๊ด€์  ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ์ง์€ ํฌ๊ฒŒ ํ•ต์‹ฌ ๊ธฐ๋Šฅ๊ณผ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์œผ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋Š”๋ฐ, ๋‘ ์ฝ”๋“œ๋ฅผ ๊ฐ™์€ ๊ณณ์— ์ž‘์„ฑํ•˜๊ฒŒ ๋˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

  • ์ค‘๋ณต๋˜๋Š” ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ ์ฝ”๋“œ๊ฐ€ ์—ฌ๋Ÿฌ ๊ณณ์— ํฉ์–ด์ ธ ์กด์žฌ

  • ํ•ต์‹ฌ ๊ธฐ๋Šฅ๊ณผ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์ด ์„ž์—ฌ ์ฝ”๋“œ๊ฐ€ ๋ณต์žกํ•ด์ง

  • ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ๋ณ€๊ฒฝํ•  ๋•Œ ํ•ต์‹ฌ ๊ธฐ๋Šฅ ์ฝ”๋“œ๋„ ํ•จ๊ป˜ ์ˆ˜์ •ํ•ด์•ผ ํ•จ

๋•Œ๋ฌธ์— ์ด๋ฅผ ๋ถ„๋ฆฌํ•˜๋ ค๋Š” ์‹œ๋„๋ฅผ ํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๊ณ , ๋ถ€๊ฐ€์ ์ธ ๊ธฐ๋Šฅ์„ ๋ถ„๋ฆฌํ•˜์—ฌ ์„ค๊ณ„ํ•˜์—ฌ ๊ฐœ๋ฐœ ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๊ด€์  ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ(AOP)์ด๋ผ๊ณ  ํ•œ๋‹ค.

์šฉ์–ด ์ •๋ฆฌ

  • ์• ์ŠคํŽ™ํŠธ(Aspect)

    • ์—ฌ๋Ÿฌ ๊ฐ์ฒด์— ๊ณตํ†ต์œผ๋กœ ์ ์šฉ๋˜๋Š” ๊ด€์‹ฌ์‚ฌ(๋ถ€๊ฐ€ ๊ธฐ๋Šฅ)์˜ ๋ชจ๋“ˆํ™”(์–ด๋“œ๋ฐ”์ด์Šค + ํฌ์ธํŠธ์ปท)

    • ์Šคํ”„๋ง์—์„œ๋Š” @Aspect ์• ๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•œ ํด๋ž˜์Šค๋กœ ๊ตฌํ˜„

  • ์กฐ์ธ ํฌ์ธํŠธ(Join point)

    • ์ถ”์ƒ์ ์ธ ๊ฐœ๋…์œผ๋กœ, ์–ด๋“œ๋ฐ”์ด์Šค๊ฐ€ ์ ์šฉ๋  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ์ง€์ ์„ ์˜๋ฏธ

    • ๋ฉ”์†Œ๋“œ ์‹คํ–‰ ์‹œ์ , ์ƒ์„ฑ์ž ํ˜ธ์ถœ ์‹œ์ , ํ•„๋“œ ๊ฐ’ ์ ‘๊ทผ ์‹œ์  ๋“ฑ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ ํ๋ฆ„์˜ ํŠน์ • ์ง€์  ๋ชจ๋‘๊ฐ€ ํ•ด๋‹น

  • ์–ด๋“œ๋ฐ”์ด์Šค(Advice)

    • ์กฐ์ธ ํฌ์ธํŠธ์—์„œ ์‹คํ–‰๋˜์–ด์•ผ ํ•  ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ ๋กœ์ง

  • ํฌ์ธํŠธ์ปท(Pointcut)

    • ์ˆ˜๋งŽ์€ ์กฐ์ธ ํฌ์ธํŠธ ์ค‘์—์„œ ์–ด๋“œ๋ฐ”์ด์Šค๋ฅผ ์ ์šฉํ•  ์ง€์ ์„ ์„ ๋ณ„ํ•˜๋Š” ๊ธฐ๋Šฅ

    • AspectJ ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌ์ฒด์ ์œผ๋กœ ์ง€์ •

  • ํƒ€๊ฒŸ(Target)

    • ์–ด๋“œ๋ฐ”์ด์Šค๊ฐ€ ์ ์šฉ๋˜๋Š” ๋Œ€์ƒ ๊ฐ์ฒด

  • ์–ด๋“œ๋ฐ”์ด์ €(Advisor)

    • ํ•˜๋‚˜์˜ ์–ด๋“œ๋ฐ”์ด์Šค์™€ ํ•˜๋‚˜์˜ ํฌ์ธํŠธ์ปท์œผ๋กœ ๊ตฌ์„ฑ๋œ ๊ฐ์ฒด

    • ์Šคํ”„๋ง AOP์—์„œ๋งŒ ์‚ฌ์šฉ๋˜๋Š” ์šฉ์–ด

  • ์œ„๋น™(Weaving)

    • ํฌ์ธํŠธ์ปท์œผ๋กœ ๊ฒฐ์ •ํ•œ ํƒ€๊ฒŸ์˜ ์กฐ์ธ ํฌ์ธํŠธ์— ์–ด๋“œ๋ฐ”์ด์Šค๋ฅผ ์ ์šฉํ•˜๋Š” ๊ณผ์ •

    • ์œ„๋น™์„ ํ†ตํ•ด ํ•ต์‹ฌ ๊ธฐ๋Šฅ ์ฝ”๋“œ์˜ ๋ณ€๊ฒฝ ์—†์ด ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค

  • AOP ํ”„๋ก์‹œ(AOP Proxy)

    • AOP ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ๋งŒ๋“  ํ”„๋ก์‹œ ๊ฐ์ฒด

JDK ๋™์  ํ”„๋ก์‹œ / CGLIB

์Šคํ”„๋ง์—์„œ ํ”„๋ก์‹œ ํŒจํ„ด์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋ก  ๋‹ค์Œ ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

JDK ๋™์  ํ”„๋ก์‹œ

  • ์ž๋ฐ” ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ธฐ์ˆ 

  • ์ธํ„ฐํŽ˜์ด์Šค ๊ธฐ๋ฐ˜์œผ๋กœ ํ”„๋ก์‹œ๋ฅผ ์ƒ์„ฑ(ํƒ€๊ฒŸ์ด ๊ตฌํ˜„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์žˆ์–ด์•ผ๋งŒ ํ”„๋ก์‹œ ์ƒ์„ฑ ๊ฐ€๋Šฅ)

  • InvocationHandler ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ํ”„๋ก์‹œ์˜ ๋™์ž‘ ์ •์˜

class TestInvocationHandler implements InvocationHandler {

    private TargetInterface target; // Target, ์ ์šฉ์ด ๋  ์‹ค์ œ ๊ฐ์ฒด

    public TestInvocationHandler(TargetInterface target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log.info("log start");
        Object result = method.invoke(target, args);  // ์‹ค์ œ ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ
        log.info("log end");

        return result;
    }
}

CGLIB

  • ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ, ๋ฐ”์ดํŠธ์ฝ”๋“œ๋ฅผ ์กฐ์ž‘ํ•˜์—ฌ ํ”„๋ก์‹œ๋ฅผ ์ƒ์„ฑ

  • ํด๋ž˜์Šค ์ƒ์† ๊ธฐ๋ฐ˜์œผ๋กœ ํ”„๋ก์‹œ๋ฅผ ์ƒ์„ฑํ•˜๋ฏ€๋กœ ์ธํ„ฐํŽ˜์ด์Šค ํ•„์š” ์—†์Œ

  • ํด๋ž˜์Šค๋‚˜ ๋ฉ”์„œ๋“œ์— final ํ‚ค์›Œ๋“œ๊ฐ€ ์žˆ์œผ๋ฉด ์ƒ์†์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๊ฑฐ๋‚˜ ์˜ค๋ฒ„๋ผ์ด๋”ฉ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— final ํ‚ค์›Œ๋“œ๊ฐ€ ์—†๋Š” ํด๋ž˜์Šค๋‚˜ ๋ฉ”์„œ๋“œ๋งŒ ์ ์šฉ ๊ฐ€๋Šฅ

  • MethodInterceptor ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ํ”„๋ก์‹œ์˜ ๋™์ž‘์„ ์ •์˜

class TestMethodInterceptor implements MethodInterceptor {

    private TargetImpl target; // Target, ์ ์šฉ์ด ๋  ์‹ค์ œ ๊ฐ์ฒด

    public TestMethodInterceptor(TargetImpl target) {
        this.target = target;
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        log.info("log start");
        Object result = proxy.invoke(target, args); // ์‹ค์ œ ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ
        log.info("log end");

        return result;
    }
}

์˜ˆ์‹œ ์ฝ”๋“œ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด ํ”„๋ก์‹œ ํŒจํ„ด์„ ๊ตฌํ˜„ํ•ด์•ผํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ๊ตฌํ˜„ํ•˜๋Š”๋ฐ ๋ณต์žก์„ฑ์„ ๊ฐ€์ง€๋Š”๋ฐ, ์Šคํ”„๋ง์—์„œ๋Š” ์ด๋ฅผ ์ถ”์ƒํ™”์‹œ์ผœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก Proxy Factory๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

Proxy Factory

Proxy Factory๋Š” ์Šคํ”„๋ง์—์„œ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํ†ต์ผํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ถ”์ƒํ™”ํ•œ ๊ฒƒ์ด๋‹ค.

Proxy Factory & Advice Call Flow

์ธํ„ฐํŽ˜์ด์Šค ์œ ๋ฌด ํ˜น์€ ์˜ต์…˜์— ๋”ฐ๋ผ JDK ๋™์  ํ”„๋ก์‹œ์™€ CGLIB๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋ก์‹œ ํŒจํ„ด์„ ๊ตฌํ˜„ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

  • Proxy Factory๋ฅผ ์ด์šฉํ•œ ์˜ˆ์‹œ ์ฝ”๋“œ

// ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•  Advice
class LogTraceAdvice implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        log.info("log start");
        Object result = invocation.proceed(); // ์‹ค์ œ ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ
        log.info("log end");

        return result;
    }
}

class ExampleProxyFactory {

    public Object getProxy(Object target) {
        // Pointcut
        NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
        pointcut.setMappedNames("request*", "order*", "save*");

        // Advice
        LogTraceAdvice advice = new LogTraceAdvice();

        // Advisor
        Advisor advisor = new DefaultPointcutAdvisor(pointcut, advice);

        return new ProxyFactory()
                .setTarget(target)
                .addAdvisor(advisor)
                .getProxy();
    }
}

class Main {

    public static void main(String[] args) {
        Example example = new Example();
        ExampleProxyFactory proxyFactory = new ExampleProxyFactory();
        Example proxy = (Example) proxyFactory.getProxy(example);
        proxy.execute();
    }
}

์ด ๋ฐฉ๋ฒ•์œผ๋กœ ์ƒ์„ฑ ๋ฐฉ๋ฒ•์€ ํ†ต์ผ๋˜์—ˆ์ง€๋งŒ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‹จ์ ์ด ์กด์žฌํ•œ๋‹ค.

  • ์ ์šฉํ•  ๋ฉ”์„œ๋“œ๋ฅผ ํ•˜๋‚˜ํ•˜๋‚˜ ์ˆ˜๋™์œผ๋กœ ๋“ฑ๋ก ํ•„์š”

  • ์ปดํฌ๋„ŒํŠธ ์Šค์บ”์„ ํ•˜๋Š” ๊ฒฝ์šฐ ํ”„๋ก์‹œ ๊ฐ์ฒด ์ƒ์„ฑ์ด ๋ถˆ๊ฐ€๋Šฅ

๋•Œ๋ฌธ์— ์ปดํฌ๋„ŒํŠธ ์Šค์บ”์„ ํฌํ•จํ•œ ๋“ฑ๋ก๋˜๋Š” ๋นˆ๋“ค์— ๋Œ€ํ•ด ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ ์šฉํ•˜๋Š” ๋นˆ ํ›„์ฒ˜๋ฆฌ๊ธฐ ๋ฐฉ๋ฒ•์ด ๋“ฑ์žฅํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

๋นˆ ํ›„์ฒ˜๋ฆฌ๊ธฐ

๋นˆ ํ›„์ฒ˜๋ฆฌ๊ธฐ๋ฅผ ์ด์šฉํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ ์Šค์บ”์„ ํฌํ•จํ•œ ๋“ฑ๋ก๋˜๋Š” ๋นˆ๋“ค์— ๋Œ€ํ•ด ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ ์šฉํ•˜์—ฌ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ๋‹ค.

// Processor.java
class PackageLogTracePostProcessor implements BeanPostProcessor {

    private final String basePackage; // ํ”„๋ก์‹œ ์ ์šฉ ํŒจํ‚ค์ง€
    private final Advisor advisor; // Advice + Pointcut

    public PackageLogTracePostProcessor(String basePackage, Advisor advisor) {
        this.basePackage = basePackage;
        this.advisor = advisor;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        String packageName = bean.getClass().getPackageName();

        // ํ”„๋ก์‹œ ์ ์šฉ ๋Œ€์ƒ ์—ฌ๋ถ€ ์ฒดํฌ
        if (!packageName.startsWith(basePackage)) {
            return bean; // ํ”„๋ก์‹œ ์ ์šฉ ๋Œ€์ƒ์ด ์•„๋‹ˆ๋ฉด ์›๋ณธ์„ ๋ฐ˜ํ™˜
        }

        // ํ”„๋ก์‹œ ๋Œ€์‹ฑ์ด๋ฉด ํ”„๋ก์‹œ๋ฅผ ๋งŒ๋“ค์–ด์„œ ๋ฐ˜ํ™˜
        return new ProxyFactory()
                .setTarget(bean)
                .addAdvisor(advisor)
                .getProxy();
    }
}

// Config.java
@Configuration
@Import({AppV1Config.class, AppV2Config.class})
class BeanPostProcessorConfig {

    @Bean
    public PackageLogTracePostProcessor logTracePostProcessor() {
        return new PackageLogTracePostProcessor("hello.proxy.app", getAdvisor());
    }

    @Bean
    public DefaultPointcutAdvisor advisor() {
        return new DefaultPointcutAdvisor(Pointcut.TRUE, new MyAdvice());
    }
}

ํ•˜์ง€๋งŒ ์ด ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ ํฌ์ธํŠธ ์ปท(=๋นˆ ํ›„์ฒ˜๋ฆฌ๊ธฐ)๊ณผ ์–ด๋“œ๋ฐ”์ด์Šค(=Proxy Factory)๋ฅผ ๋ณ„๋„๋กœ ์ •์˜ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ์ „ํžˆ ๋ณต์žกํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๊ธฐ ์–ด๋ ต๋‹ค๋Š” ๋‹จ์ ์ด ์กด์žฌํ•œ๋‹ค.

@Aspect

ํ”„๋ก์‹œ๋ฅผ ์ง์ ‘ ์ƒ์„ฑํ•˜์—ฌ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์•„๋‹Œ CGLib๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ”์ดํŠธ ์ฝ”๋“œ๋ฅผ ์กฐ์ž‘ํ•˜์—ฌ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ, ๊ฐ€์žฅ ๊ฐ„๋‹จํ•˜๊ฒŒ AOP๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

// Aspect.java
@Aspect
class ExampleAspect {

    @Around(value = "execution(* hello.proxy.app..*(..))") // Pointcut
    public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
        // Advice ๋กœ์ง
        // ...

        Object result = joinPoint.proceed(); // ์‹ค์ œ ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ

        // ...
        // Advice ๋กœ์ง
        return result;
    }
}

// Config.java
@Configuration
class AopConfig {

    @Bean
    public LogTraceAspect logTraceAspect(LogTrace logTrace) {
        return new LogTraceAspect(logTrace);
    }
}

ํฌ์ธํŠธ์ปท(Pointcut)๊ณผ ์–ด๋“œ๋ฐ”์ด์Šค(Advice)๋กœ ๊ตฌ์„ฑ๋œ ์–ด๋“œ๋ฐ”์ด์ €(Advisor)์˜ ์ƒ์„ฑ์„ ํŽธ๋ฆฌํ•˜๊ฒŒ ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ๊ฐ€์ง„ ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ํ›จ์”ฌ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค.

@Aspect์˜ ๋™์ž‘ ๋ฐฉ์‹

@Aspect๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ ์šฉํ•  ๋•Œ, ์–ด๋“œ๋ฐ”์ด์ € ์ƒ์„ฑ๊ณผ ํ”„๋ก์‹œ ๊ฐ์ฒด ์ ์šฉ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ๋ฆ„์œผ๋กœ ๋™์ž‘ํ•˜๊ฒŒ ๋œ๋‹ค.

  • ์–ด๋“œ๋ฐ”์ด์ € ์ž๋™ ํƒ์ƒ‰ ๋ฐ ์ƒ์„ฑ

    1. ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ ์ดˆ๊ธฐํ™” ์‹œ @Aspect ์• ๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ๋นˆ ์กฐํšŒ

    2. @Aspect ์• ๋…ธํ…Œ์ด์…˜ ์ •๋ณด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์–ด๋“œ๋ฐ”์ด์ € ์ƒ์„ฑ

    3. ์–ด๋“œ๋ฐ”์ด์ € ๋“ฑ๋ก

@Aspect ์‚ฌ์šฉ ์‹œ ํ”„๋ก์‹œ ๊ฐ์ฒด ๋“ฑ๋ก ๊ณผ์ •
  • ํ”„๋ก์‹œ ๊ฐ์ฒด ์ ์šฉ

    1. ์Šคํ”„๋ง ๋นˆ ๋Œ€์ƒ์ด ๋˜๋Š” ๊ฐ์ฒด ์ƒ์„ฑ

    2. ์ƒ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ๋“ฑ๋ก๋˜๋Š” ๋ชจ๋“  ๋นˆ์— ๋Œ€ํ•ด BeanPostProcessor๋ฅผ ํ†ตํ•ด 2์ฐจ ๊ฐ€๊ณต ์‹œ๋„

    3. ์Šคํ”„๋ง ๋นˆ ์ปจํ…Œ์ด๋„ˆ์—์„œ ์–ด๋“œ๋ฐ”์ด์ € ์กฐํšŒ

    4. ์ƒ์„ฑ๋œ ๋นˆ์ด ์บ์‹ฑ๋œ ์–ด๋“œ๋ฐ”์ด์ €๋“ค์˜ ํฌ์ธํŠธ์ปท ์กฐ๊ฑด ๋Œ€์ƒ์ธ์ง€ ๊ฒ€์‚ฌ

    5. ๋Œ€์ƒ์ด๋ผ๋ฉด, ํ”„๋ก์‹œ ํŒฉํ† ๋ฆฌ๋ฅผ ํ†ตํ•ด ํ•ด๋‹น ๋นˆ์˜ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ(์›๋ณธ ๊ฐ์ฒด๋Š” ํ”„๋ก์‹œ ๋‚ด๋ถ€์—์„œ ์ฐธ์กฐ)

    6. ์›๋ณธ ๊ฐ์ฒด ๋Œ€์‹  ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก

ํ”„๋ก์‹œ ๋‚ด๋ถ€ ํ˜ธ์ถœ (Self-Invocation) ๋ฌธ์ œ

AOP ํ”„๋ก์‹œ๊ฐ€ ์ ์šฉ๋œ ๊ฐ์ฒด์˜ ๋‚ด๋ถ€์—์„œ ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ AOP๊ฐ€ ์ ์šฉ๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋Š” ํ”„๋ก์‹œ๋ฅผ ๊ฑฐ์น˜์ง€ ์•Š๊ณ  this ์ฐธ์กฐ๋ฅผ ํ†ตํ•ด ์›๋ณธ ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.


@Service
class MyService {

    public void external() {
        // ... ๋กœ์ง ...
        this.internal(); // ํ”„๋ก์‹œ๋ฅผ ๊ฑฐ์น˜์ง€ ์•Š๊ณ  ์›๋ณธ ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ง์ ‘ ํ˜ธ์ถœ
    }

    @Transactional
    public void internal() {
        // ํŠธ๋žœ์žญ์…˜์ด ์ ์šฉ๋˜๊ธฐ๋ฅผ ๊ธฐ๋Œ€ํ•˜๋Š” ๋กœ์ง
    }
}

์œ„ ์ฝ”๋“œ์—์„œ external()์„ ํ˜ธ์ถœํ•˜๋ฉด internal()์€ ํŠธ๋žœ์žญ์…˜ ์–ด๋“œ๋ฐ”์ด์Šค๋ฅผ ํƒ€์ง€ ์•Š๋Š”๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • ์ž๊ธฐ ์ž์‹  ์ฃผ์ž…: ์ƒ์„ฑ์ž๋‚˜ @Autowired๋ฅผ ํ†ตํ•ด ํ”„๋ก์‹œ ๊ฐ์ฒด์ธ ์ž๊ธฐ ์ž์‹ ์„ ์ฃผ์ž…๋ฐ›์•„ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ์‹

  • ์ง€์—ฐ ์กฐํšŒ: ApplicationContext๋‚˜ ObjectProvider๋ฅผ ์‚ฌ์šฉํ•ด ์‹ค์ œ ํ•„์š”ํ•œ ์‹œ์ ์— ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์กฐํšŒ(lookup)ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹

  • ๊ตฌ์กฐ ๋ณ€๊ฒฝ: ์Šคํ”„๋ง์ด ๊ฐ€์žฅ ๊ถŒ์žฅํ•˜๋Š” ๋ฐฉ๋ฒ• ๋‚ด๋ถ€ ํ˜ธ์ถœ์ด ํ•„์š”ํ•œ ๋กœ์ง์„ ๋ณ„๋„์˜ ํด๋ž˜์Šค๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ์˜์กด์„ฑ์„ ์ฃผ์ž…๋ฐ›์•„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹

์Šคํ”„๋ง๊ณผ CGLIB

์ตœ์‹  ๋ฒ„์ „์˜ ์Šคํ”„๋ง ๋ถ€ํŠธ์—์„œ๋Š” ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ๊ธฐ๋ณธ์ ์œผ๋กœ CGLIB๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ์ด๋ฅผ ํ†ตํ•ด ์•„๋ž˜์™€ ๊ฐ™์€ ์žฅ์ ์„ ๊ฐ€์ง€๊ฒŒ ๋œ๋‹ค.

  • ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์—†๋Š” ํด๋ž˜์Šค๋„ ํ”„๋ก์‹œ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Œ

  • ์˜์กด๊ด€๊ณ„ ์ฃผ์ž… ์‹œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Œ(JDK ๋™์  ํ”„๋ก์‹œ๋Š” ๋ฐœ์ƒ)

ํ•˜์ง€๋งŒ CGLIB๋Š” ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์•„ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ์‹์ด๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ œ์•ฝ์‚ฌํ•ญ์ด ์กด์žฌํ–ˆ์ง€๋งŒ 3๋ฒˆ์„ ์ œ์™ธํ•˜๊ณ ๋Š” ์ด๋ฏธ ํ•ด๊ฒฐ๋˜์—ˆ๋‹ค.(objenesis๋ผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๊ฒฐ)

  1. ๋Œ€์ƒ ํด๋ž˜์Šค์— ๊ธฐ๋ณธ ์ƒ์„ฑ์ž๊ฐ€ ๋ฐ˜๋“œ์‹œ ์กด์žฌํ•ด์•ผ ํ•จ

  2. ์ƒ์„ฑ์ž ํ˜ธ์ถœ์ด ๋‘ ๋ฒˆ ๋ฐœ์ƒ(์‹ค์ œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ๋•Œ + ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ๋•Œ)

  3. final ํด๋ž˜์Šค, final ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ํ”„๋ก์‹œ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์—†์Œ

3๋ฒˆ ๋ฌธ์ œ๋Š” ์•„์ง ํ•ด๊ฒฐํ•˜์ง€ ๋ชปํ–ˆ์œผ๋‚˜ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ final ํ‚ค์›Œ๋“œ๋ฅผ ์ž˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ํฐ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š๋Š”๋‹ค.

์ฐธ๊ณ ์ž๋ฃŒ

Last updated

Was this helpful?