AspectProxy

@Aspect AOP

์Šคํ”„๋ง ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํ”„๋ก์‹œ๋ฅผ ์ ์šฉํ•˜๋ ค๋ฉด ํฌ์ธํŠธ์ปท๊ณผ ์–ด๋“œ๋ฐ”์ด์Šค๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋Š” ์–ด๋“œ๋ฐ”์ด์ €(Advisor)๋ฅผ ๋งŒ๋“ค์–ด์„œ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•˜๋ฉด ๋œ๋‹ค.

๊ทธ๋Ÿฌ๋ฉด ์ž๋™ ํ”„๋ก์‹œ ์ƒ์„ฑ๊ธฐ๋Š” ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋œ ์–ด๋“œ๋ฐ”์ด์ €๋“ค์„ ์ฐพ๊ณ  ์Šคํ”„๋ง ๋นˆ๋“ค์— ์ž๋™์œผ๋กœ ํ”„๋ก์‹œ๋ฅผ ์ ์šฉํ•ด์ฃผ๋Š” ์ž‘์—…๋“ค์„ ์ฒ˜๋ฆฌํ•ด์ค€๋‹ค.

์Šคํ”„๋ง์€ @Aspect ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ๋งค์šฐ ํŽธ๋ฆฌํ•˜๊ฒŒ ํฌ์ธํŠธ์ปท๊ณผ ์–ด๋“œ๋ฐ”์ด์Šค๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋Š” ์–ด๋“œ๋ฐ”์ด์ € ์ƒ์„ฑ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•œ๋‹ค.

์ฐธ๊ณ  : @Aspect๋Š” ๊ด€์  ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ(AOP)์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š” AspectJ ํ”„๋กœ์ ํŠธ์—์„œ ์ œ๊ณตํ•˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ด๋‹ค. ์Šคํ”„๋ง์ธ ์ด๊ฒƒ์„ ์ฐจ์šฉํ•ด์„œ ํ”„๋ก์‹œ๋ฅผ ํ†ตํ•œ AOP๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•œ๋‹ค.

@Aspect
@RequiredArgsConstructor
public class LogTraceAspect {
    private final LogTrace logTrace;

    @Around("execution(* hello.proxy.app..*(..))")
    public Object execute(ProceedingJoinPoint joinPoint) throws Throwable{
        TraceStatus status = null;
        try {
            String message = joinPoint.getSignature().toShortString();
            status = logTrace.begin(message);

            Object result = joinPoint.proceed();

            logTrace.end(status);
            return result;
        } catch (Exception e) {
            logTrace.exception(status, e);
            throw e;
        }
    }
}
  • @Aspect : ์–ด๋…ธํ…Œ์ด์…˜ ๊ธฐ๋ฐ˜ ํ”„๋ก์‹œ๋ฅผ ์ ์šฉํ•  ๋•Œ ํ•„์š”ํ•˜๋‹ค.

  • @Around : ํฌ์ธํŠธ์ปท ํ‘œํ˜„์‹์„ ๋„ฃ๋Š”๋‹ค. ํ‘œํ˜„์‹์€ AspectJ ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•œ๋‹ค. @Around์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ์–ด๋“œ๋ฐ”์ด์Šค๊ฐ€ ๋œ๋‹ค.

  • ProceedingJointPoint joinPoint : ์–ด๋“œ๋ฐ”์ด์Šค์— MethodInvocation invocation๊ณผ ์œ ์‚ฌํ•œ ๊ธฐ๋Šฅ์ด๋‹ค. ๋‚ด๋ถ€์— ์‹ค์ œ ํ˜ธ์ถœ ๋Œ€์ƒ, ์ „๋‹ฌ ์ธ์ž, ์–ด๋–ค ๊ฐ์ฒด์™€ ์–ด๋–ค ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜์—ˆ๋Š”์ง€ ์ •๋ณด๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋‹ค.

  • joinPoint.proceed() : ์‹ค์ œ ํ˜ธ์ถœ ๋Œ€์ƒ(target)์„ ํ˜ธ์ถœํ•œ๋‹ค.

@Configuration
@Import({AppV1Config.class, AppV2Config.class})
public class AopConfig {

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

@Import(AopConfig.class)
@SpringBootApplication(scanBasePackages = "hello.proxy.app.v3")
public class ProxyApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProxyApplication.class, args);
    }

    @Bean
    public LogTrace logTrace() {
        return new ThreadLocalLogTrace();
    }
}
  • @Aspect๊ฐ€ ์žˆ์–ด๋„ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•ด ์ฃผ์–ด์•ผ ํ•œ๋‹ค. @Component๋กœ ์ปดํฌ๋„ŒํŠธ ์Šค์บ”์„ ์‚ฌ์šฉํ•ด๋„ ๋œ๋‹ค.

@Aspect ํ”„๋ก์‹œ - ์„ค๋ช…

์ž๋™ ํ”„๋ก์‹œ ์ƒ์„ฑ๊ธฐ(AnnotationAwareAspectHAutoProxyCreator)๋Š” Advisor๋ฅผ ์ž๋™์œผ๋กœ ์ฐพ์•„์™€์„œ ํ•„์š”ํ•œ ๊ณณ์— ํ”„๋ก์‹œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ ์šฉํ•ด์ค€๋‹ค. ์ž๋™ ํ”„๋ก์‹œ ์ƒ์„ฑ๊ธฐ๋Š” ์—ฌ๊ธฐ์— ์ถ”๊ฐ€๋กœ ํ•˜๋‚˜์˜ ์—ญํ• ์„ ๋”ํ•˜๋Š”๋ฐ ๋ฐ”๋กœ @Aspect๋ฅผ ์ฐฝ์ž์„œ ์ด๊ฒƒ์„ Advisor๋กœ ๋งŒ๋“ค์–ด์ค€๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋ฆ„ ์•ž์— AnnotationAware(์–ด๋…ธํ…Œ์ด์…˜์„ ์ธ์‹ํ•˜๋Š”) ๊ฐ€ ๋ถ™์–ด ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

img.png

์ž๋™ ํ”„๋ก์‹œ ์ƒ์„ฑ๊ธฐ๋Š” 2๊ฐ€์ง€ ์ผ์„ ํ•œ๋‹ค.

  1. @Aspect๋ฅผ ๋ณด๊ณ  ์–ด๋“œ๋ฐ”์ด์ €๋กœ ๋ณ€ํ™˜ํ•ด์„œ ์ €์žฅํ•œ๋‹ค.

  2. ์–ด๋“œ๋ฐ”์ด์ €๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ”„๋ก์‹œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

img_1.png
  1. ์‹คํ–‰ : ์Šคํ”„๋ง ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ๋”ฉ ์‹œ์ ์— ์ž๋™ ํ”„๋ก์‹œ ์ƒ์„ฑ๊ธฐ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

  2. ๋ชจ๋“  @Aspect ๋นˆ ์กฐํšŒ : ์ž๋™ ํ”„๋ก์‹œ ์ƒ์„ฑ๊ธฐ๋Š” ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์—์„œ @Aspect ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ์Šคํ”„๋ง ๋นˆ์„ ๋ชจ๋‘ ์กฐํšŒํ•œ๋‹ค.

  3. ์–ด๋“œ๋ฐ”์ด์ € ์ƒ์„ฑ : @Aspec ์–ด๋“œ๋ฐ”์ด์ € ๋นŒ๋”๋ฅผ ํ†ตํ•ด @Aspect ์–ด๋…ธํ…Œ์ด์…˜ ์ •๋ณด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์–ด๋“œ๋ฐ”์ด์ €๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

  4. @Aspect๊ธฐ๋ฐ˜ ์–ด๋“œ๋ฐ”์ด์ € ์ €์žฅ : ์ƒ์„ฑํ•œ ์–ด๋“œ๋ฐ”์ด์ €๋ฅผ @Aspect ์–ด๋“œ๋ฐ”์ด์ € ๋นŒ๋” ๋‚ด๋ถ€์— ์ €์žฅํ•œ๋‹ค.

@Aspect ์–ด๋“œ๋ฐ”์ด์ € ๋นŒ๋” @Aspect ์˜ ์ •๋ณด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํฌ์ธํŠธ์ปท, ์–ด๋“œ๋ฐ”์ด์Šค, ์–ด๋“œ๋ฐ”์ด์ €๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๋ณด๊ด€ํ•˜๋Š” ๊ฒƒ์„ ๋‹ด๋‹นํ•œ๋‹ค. @Aspect ์˜ ์ •๋ณด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์–ด๋“œ๋ฐ”์ด์ €๋ฅผ ๋งŒ๋“ค๊ณ  @Aspect ์–ด๋“œ๋ฐ”์ด์ € ๋นŒ๋” ๋‚ด๋ถ€ ์ €์žฅ์†Œ์— ์บ์‹œํ•œ๋‹ค. ์บ์‹œ์— ์–ด๋“œ๋ฐ”์ด์ €๊ฐ€ ์ด๋ฏธ ๋งŒ๋“ค์–ด์ ธ ์žˆ๋Š” ๊ฒฝ์šฐ ์บ์‹œ์— ์ €์žฅ๋œ ์–ด๋“œ๋ฐ”์ด์ €๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

img_2.png
  1. ์ƒ์„ฑ : ์Šคํ”„๋ง ๋นˆ ๋Œ€์ƒ์ด ๋˜๋Š” ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.(@Bean, ์ปดํฌ๋„ŒํŠธ ์Šค์บ” ๋ชจ๋‘ ํฌํ•จ)

  2. ์ „๋‹ฌ : ์ƒ์„ฑ๋œ ๊ฐ์ฒด๋ฅผ ๋นˆ ์ €์žฅ์†Œ์— ๋“ฑ๋กํ•˜๊ธฐ ์ง์ „์— ๋นˆ ํ›„์ฒ˜๋ฆฌ๊ธฐ์— ์ „๋‹ฌํ•œ๋‹ค.

    • 1. Advisor ๋นˆ ์กฐํšŒ : ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์—์„œ Advisor๋นˆ์„ ๋ชจ๋‘ ์กฐํšŒํ•œ๋‹ค.

    • 2. @Aspect Advisor ์กฐํšŒ : @Aspect ์–ด๋“œ๋ฐ”์ด์ € ๋นŒ๋” ๋‚ด๋ถ€์— ์ €์žฅ๋œ Advisor๋ฅผ ๋ชจ๋‘ ์กฐํšŒํ•œ๋‹ค.

  3. ํ”„๋ก์‹œ ์ ์šฉ ๋Œ€์ƒ ์ฒดํฌ : 3-1,3-2์—์„œ ์กฐํšŒํ•œ Advisor์— ํฌํ•จ๋˜์–ด ์žˆ๋Š” ํฌ์ธํŠธ์ปท์„ ์‚ฌ์šฉํ•ด์„œ ํ•ด๋‹น ๊ฐ์ฒด๊ฐ€ ํ”„๋ก์‹œ๋ฅผ ์ ์šฉํ•  ๋Œ€์ƒ์ธ์ง€ ํŒ๋‹จํ•œ๋‹ค. ์ด๋•Œ ๊ฐ์ฒด์˜ ํด๋ž˜์Šค ์ •๋ณด๋ฅผ ํฌํ•จ ํ•ด๋‹น ๊ฐ์ฒด์˜ ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋ฅผ ํฌ์ธํŠธ์ปท์— ๋น„๊ตํ•ด์„œ ์กฐ๊ฑด์ด ํ•˜๋‚˜๋ผ๋„ ๋งŒ์กฑํ•˜๋ฉด ํ”„๋ก์‹œ ์ ์šฉ ๋Œ€์ƒ์ด ๋œ๋‹ค.

  4. ํ”„๋ก์‹œ ์ƒ์„ฑ : ํ”„๋ก์‹œ ์ ์šฉ ๋Œ€์ƒ์ด๋ฉด ํ”„๋ก์‹œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํ”„๋ก์‹œ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ํ”„๋ก์‹œ ์ ์šฉ ๋Œ€์ƒ์ด ์•„๋‹ˆ๋ผ๋ฉด ์›๋ณธ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

  5. ๋นˆ ๋“ฑ๋ก : ๋ฐ˜ํ™˜๋œ ๊ฐ์ฒด๋Š” ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋œ๋‹ค.

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „๋ฐ˜์— ๋กœ๊ทธ๋ฅผ ๋‚จ๊ธฐ๋Š” ๊ธฐ๋Šฅ์€ ํŠน์ • ๊ธฐ๋Šฅ ํ•˜๋‚˜์— ๊ด€์‹ฌ์ด ์žˆ๋Š” ๊ธฐ๋Šฅ์ด ์•„๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ๋“ค ์‚ฌ์ด์— ๊ฑธ์ณ์„œ ๋“ค์–ด๊ฐ€๋Š” ๊ด€์‹ฌ์‚ฌ์ด๋‹ค.

์ด๊ฒƒ์„ ํšก๋‹จ ๊ด€์‹ฌ์‚ฌ(cross-cutting concerns)๋ผ๊ณ  ํ•œ๋‹ค.

img_3.png

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

Last updated