SpringAopImplement_4_6
์คํ๋ง AOP ๊ตฌํ - V4
ํฌ์ธํธ์ปท ์ฐธ์กฐ
ํฌ์ธํธ์ปท์ ๊ณต์ฉ์ผ๋ก ์ฌ์ฉํ๊ธฐ ์ํด ๋ณ๋์ ์ธ๋ถ ํด๋์ค์ ๋ชจ์๋์ด๋ ๋๋ค.
public class Pointcuts {
    @Pointcut("execution(* hello.aop.order..*(..))")
    public void allOrder(){} //ํฌ์ธํธ์ปท ์๊ทธ๋์ฒ
    //ํด๋์ค ์ด๋ฆ ํจํด์ด *Service
    @Pointcut("execution(* *..*Service.*(..))")
    public void allService(){}
    @Pointcut("allOrder() && allService()")
    public void orderAndService(){}
}์ธ๋ถ์์ ํธ์ถํ๊ธฐ ์ํด
public์ผ๋ก ์ด์ด๋์ด์ผ ํ๋ค.
@Slf4j
@Aspect
public class AspectV4Pointcut {
    @Around("Pointcuts.allOrder()")
    public Object doLog(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("[log] {}", joinPoint.getSignature());
        return joinPoint.proceed();
    }
    //hello.aop.order ํจํค์ง์ ํ์ ํจํค์ง ์ด๋ฉด์ ๋์์ ํด๋์ค ์ด๋ฆ ํจํด์ด *Service
    @Around("Pointcuts.orderAndService()")
    public Object doTransaction(ProceedingJoinPoint joinPoint) throws Throwable {
        try {
            log.info("[ํธ๋์ญ์
 ์์] {}", joinPoint.getSignature());
            Object result = joinPoint.proceed();
            log.info("[ํธ๋์ญ์
 ์ปค๋ฐ] {}", joinPoint.getSignature());
            return result;
        } catch (Exception e) {
            log.info("[ํธ๋์ญ์
 ๋กค๋ฐฑ] {}", joinPoint.getSignature());
            throw e;
        } finally {
            log.info("[๋ฆฌ์์ค ๋ฆด๋ฆฌ์ฆ] {}", joinPoint.getSignature());
        }
    }
}์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ํด๋์ค ์ด๋ฆ๊ณผ ํฌ์ธํธ์ปท ์๊ทธ๋์ฒ๋ฅผ ์ง์ ํ๋ฉด ๋๋ค.
ํฌ์ธํธ์ปท์ ๋ชจ์๋ ํด๋์ค์ ํฌ์ธํธ์ปท์ ์ฌ์ฉํ๋ ค๋ ํด๋์ค์ ํจํค์ง๊ฐ ๋ค๋ฅด๋ค๋ฉด ํฌ์ธํธ์ปท์ ์ฌ์ฉํ๋ ค๋ ํด๋์ค์์ ํจํค์ง๋ช ๊น์ง ํฌํจํด ์ฃผ์ด์ผ ํ๋ค.
@Slf4j
@SpringBootTest
@Import(AspectV4Pointcut.class)
public class AopTest { ... }์คํ ๊ฒฐ๊ณผ๋ ๊ธฐ์กด๊ณผ ๋๊ฐ๋ค.
์คํ๋ง AOP ๊ตฌํ - V5
์ด๋๋ฐ์ด์ค ์์
์ด๋๋ฐ์ด์ค๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์์๋ฅผ ๋ณด์ฅํ์ง ์๋๋ค. ์์๋ฅผ ์ง์ ํ๊ณ  ์ถ์ผ๋ฉด @Aspect ์ง์  ๋จ์๋ก @Order ์ด๋
ธํ
์ด์
์ ์ ์ฉํด์ผ ํ๋ค. ๋ฌธ์ ๋ ์ด๊ฒ์ ์ด๋๋ฐ์ด์ค ๋จ์๊ฐ ์๋๋ผ ํด๋์ค ๋จ์๋ก ์ ์ฉํด์ผ ํ๋ค๋ ์ ์ด๋ค.
ํ๋์ ์ ์คํํธ์ ์ฌ๋ฌ ์ด๋๋ฐ์ด์ค๊ฐ ์์ผ๋ฉด ์์๋ฅผ ๋ณด์ฅ ๋ฐ์ ์ ์๊ณ  ์ ์คํํธ๋ฅผ ๋ณ๋์ ํด๋์ค๋ก ๋ถ๋ฆฌํด์ผ ํ๋ค.
@Slf4j
public class AspectV5Order {
    @Aspect
    @Order(2)
    public static class LogAspect{
        @Around("Pointcuts.allOrder()")
        public Object doLog(ProceedingJoinPoint joinPoint) throws Throwable {
            log.info("[log] {}", joinPoint.getSignature());
            return joinPoint.proceed();
        }
    }
    @Aspect
    @Order(1)
    public static class TxAspect{
        //hello.aop.order ํจํค์ง์ ํ์ ํจํค์ง ์ด๋ฉด์ ๋์์ ํด๋์ค ์ด๋ฆ ํจํด์ด *Service
        @Around("Pointcuts.orderAndService()")
        public Object doTransaction(ProceedingJoinPoint joinPoint) throws Throwable {
            try {
                log.info("[around][ํธ๋์ญ์
 ์์] {}", joinPoint.getSignature());
                Object result = joinPoint.proceed();
                log.info("[around][ํธ๋์ญ์
 ์ปค๋ฐ] {}", joinPoint.getSignature());
                return result;
            } catch (Exception e) {
                log.info("[around][ํธ๋์ญ์
 ๋กค๋ฐฑ] {}", joinPoint.getSignature());
                throw e;
            } finally {
                log.info("[around][๋ฆฌ์์ค ๋ฆด๋ฆฌ์ฆ] {}", joinPoint.getSignature());
            }
        }
    }
}ํ๋์ ์ ์คํํธ ์์ ์๋ค ์ด๋๋ฐ์ด์ค๋ฅผ ๊ฐ๊ฐ ๋ด๋ถ ํด๋์ค๋ก ๋ถ๋ฆฌํ๋ค. (๊ฐ๊ฐ ๋ณ๋์ ํด๋์ค๋ก ๋ง๋ค์ด๋ ๋๋ค.)
๊ฐ ์ ์คํํธ์
@Order์ด๋ ธํ ์ด์ ์ ํตํด ์คํ ์์๋ฅผ ์ ์ฉํ๋ค.
@Slf4j
@SpringBootTest
@Import({AspectV5Order.TxAspect.class, AspectV5Order.LogAspect.class})
public class AopTest { ... }๋ ๊ฐ์ ํด๋์ค๋ฅผ ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋กํด์ผ ํ๋ค.
## success() ์คํ ๊ฒฐ๊ณผ ์ฝ์
[ํธ๋์ญ์
 ์์] void hello.aop.order.OrderService.orderItem(String)
[log] void hello.aop.order.OrderService.orderItem(String)
[orderService] ์คํ
[log] String hello.aop.order.OrderRepository.save(String)
[orderRepository] ์คํ
[ํธ๋์ญ์
 ์ปค๋ฐ] void hello.aop.order.OrderService.orderItem(String)
[๋ฆฌ์์ค ๋ฆด๋ฆฌ์ฆ] void hello.aop.order.OrderService.orderItem(String)ํธ๋์ญ์  ์ด๋๋ฐ์ด์ค๊ฐ ๋จผ์  ์คํ๋๊ณ ์ดํ์ ๋ก๊ทธ ์ด๋๋ฐ์ด์ค๊ฐ ์ ์ฉ๋๋ค.

์คํ๋ง AOP ๊ตฌํ - V6
์ด๋๋ฐ์ด์ค ์ข
๋ฅ
@Around: ๋ฉ์๋ ํธ์ถ ์ ํ์ ์ํ์ผ๋ก ๊ฐ์ฅ ๊ฐ๋ ฅํ ์ด๋๋ฐ์ด์ค๋ค. ์กฐ์ธ ํฌ์ธํธ ์คํ ์ฌ๋ถ ์ ํ, ๋ฐํ ๊ฐ ๋ณํ, ์์ธ ๋ณํ ๋ฑ์ด ๊ฐ๋ฅํ๋ค.@Before: ์กฐ์ธ ํฌ์ธํธ ์คํ ์ด์ ์ ์คํ@AfterReturning: ์กฐ์ธ ํฌ์ธํธ๊ฐ ์ ์ ์๋ฃํ ์คํ@AfterThrowing: ๋ฉ์๋๊ฐ ์์ธ๋ฅผ ๋์ง๋ ๊ฒฝ์ฐ ์คํ@After: ์กฐ์ธ ํฌ์ธํธ๊ฐ ์ ์ ๋๋ ์์ธ์ ๊ด๊ณ์์ด ์คํ(finally์ ๋น์ท)
@Slf4j
@Aspect
public class AspectV6Advice {
    @Around("Pointcuts.orderAndService()")
    public Object doTransaction(ProceedingJoinPoint joinPoint) throws Throwable {
        try {
            //@Before
            log.info("[ํธ๋์ญ์
 ์์] {}", joinPoint.getSignature());
            Object result = joinPoint.proceed();
            //@AfterReturning
            log.info("[ํธ๋์ญ์
 ์ปค๋ฐ] {}", joinPoint.getSignature());
            return result;
        } catch (Exception e) {
            //@AfterThrowing
            log.info("[ํธ๋์ญ์
 ๋กค๋ฐฑ] {}", joinPoint.getSignature());
            throw e;
        } finally {
            //@After
            log.info("[๋ฆฌ์์ค ๋ฆด๋ฆฌ์ฆ] {}", joinPoint.getSignature());
        }
    }
    @Before("Pointcuts.orderAndService()")
    public void deBefore(JoinPoint joinPoint) {
        log.info("[before] {}", joinPoint.getSignature());
    }
    @AfterReturning(value = "Pointcuts.orderAndService()", returning = "result")
    public void doReturn(JoinPoint joinPoint, Object result){
        log.info("[return] {} return={}", joinPoint.getSignature(), result);
    }
    @AfterThrowing(value = "Pointcuts.orderAndService()", throwing = "ex")
    public void doThrowing(JoinPoint joinPoint, Exception ex) {
        log.info("[ex] {} message={}", joinPoint.getSignature(), ex.getMessage());
    }
    @After(value = "Pointcuts.orderAndService()")
    public void doAfter(JoinPoint joinPoint) {
        log.info("[after] {}", joinPoint.getSignature());
    }
}์ฌ์ค
@Around๋ฅผ ์ ์ธํ ์ด๋๋ฐ์ด์ค๋ค์@Around๊ฐ ํ ์ ์๋ ์ผ์ ์ผ๋ถ๋ง ์ ๊ณตํ ๋ฟ์ด๋ค. ๋ฐ๋ผ์@Around์ด๋๋ฐ์ด์ค๋ง ์ฌ์ฉํด๋ ํ์ํ ๊ธฐ๋ฅ์ ๋ชจ๋ ์ํํ ์ ์๋ค.๋ชจ๋ ์ด๋๋ฐ์ด์ค๋
JoinPoint๋ฅผ ์ฒซ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ์ ์ฌ์ฉํ ์ ์๋ค.(์๋ต ๊ฐ๋ฅ)@Around๋ProceedingJoinPoint๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.ProceedingJoinPoint๋JoinPoint์ ํ์ ํ์ ์ด๋ค.
JoinPoint ์ธํฐํ์ด์ค ์ฃผ์ ๊ธฐ๋ฅ
getArgs(): ๋ฉ์๋ ์ธ์๋ฅผ ๋ฐํgetThis(): ํ๋ก์ ๊ฐ์ฒด๋ฅผ ๋ฐํgetTarget(): ๋์ ๊ฐ์ฒด๋ฅผ ๋ฐํgetSignature(): ์กฐ์ธ๋๋ ๋ฉ์๋์ ๋ํ ์ค๋ช ์ ๋ฐํtoString(): ์กฐ์ธ๋๋ ๋ฐฉ๋ฒ์ ๋ํ ์ ์ฉํ ์ค๋ช ์ ์ธ์
ProceedingJointPoint ์ธํฐํ์ด์ค ์ฃผ์ ๊ธฐ๋ฅ
proceed(): ๋ค์ ์ด๋๋ฐ์ด์ค๋ ํ๊ฒ์ ํธ์ถ
@Before
์กฐ์ธ ํฌ์ธํธ ์คํ ์ 
@Before("Pointcuts.orderAndService()")
public void deBefore(JoinPoint joinPoint) {
    log.info("[before] {}", joinPoint.getSignature());
}@Around์ ๋ค๋ฅด๊ฒ ์์ ํ๋ฆ์ ๋ณ๊ฒฝํ ์๋ ์๋ค.@Around๋ProceedingJoinPoint.proceed()๋ฅผ ํธ์ถํด์ผ ๋ค์ ๋์์ด ํธ์ถ๋๋ค. ๋ง์ฝ ํธ์ถํ์ง ์์ผ๋ฉด ๋ค์ ๋์์ด ํธ์ถ๋์ง ์๋๋ค.@Befores๋ProceedingJoinPoint.proceed()์์ฒด๋ฅผ ์ฌ์ฉํ์ง ์๋๋ค. ๋ฉ์๋ ์ข ๋ฃ ์ ์๋์ผ๋ก ๋ค์ ํ๊ฒ์ด ํธ์ถ๋๋ค.๋ฌผ๋ก ์์ธ๊ฐ ๋ฐ์ํ๋ฉด ๋ค์ ์ฝ๋๊ฐ ํธ์ถ๋์ง๋ ์๋๋ค.
@AfterReturning
๋ฉ์๋ ์คํ์ด ์ ์์ ์ผ๋ก ๋ฐํ๋ ๋ ์ฌ์ฉ
@AfterReturning(value = "Pointcuts.orderAndService()", returning = "result")
public void doReturn(JoinPoint joinPoint, Object result){
    log.info("[return] {} return={}", joinPoint.getSignature(), result);
}returning์์ฑ์ ์ฌ์ฉ๋ ์ด๋ฆ์ ์ด๋๋ฐ์ด์ค ๋ฉ์๋์ ๋งค๊ฐ๋ณ์ ์ด๋ฆ๊ณผ ์ผ์นํด์ผ ํ๋ค.returning์ ์ ์ง์ ๋ ํ์ ์ ๊ฐ์ ๋ฐํํ๋ ๋ฉ์๋๋ง ๋์์ผ๋ก ์คํํ๋ค.(๋ถ๋ชจ ํ์ ์ ์ง์ ํ๋ฉด ์์ ํ์ ๋ ์ธ์ )@Around์ ๋ค๋ฅด๊ฒ ๋ฐํ๋๋ ๊ฐ์ฒด๋ฅผ ๋ณ๊ฒฝํ ์๋ ์๋ค. ๋ฐํ ๊ฐ์ฒด๋ฅผ ๋ณ๊ฒฝํ๋ ค๋ฉด@Around๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.๋ฐํ ๊ฐ์ฒด๋ฅผ ์กฐ์ํ ์๋ ์๋ค.
@AfterThrowing
๋ฉ์๋ ์คํ์ด ์์ธ๋ฅผ ๋์ ธ์ ์ข ๋ฃ๋ ๋ ์คํ
@AfterThrowing(value = "Pointcuts.orderAndService()", throwing = "ex")
public void doThrowing(JoinPoint joinPoint, Exception ex) {
    log.info("[ex] {} message={}", joinPoint.getSignature(), ex.getMessage());
}throwing์์ฑ์ ์ฌ์ฉ๋ ์ด๋ฆ์ ์ด๋๋ฐ์ด์ค ๋ฉ์๋์ ๋งค๊ฐ๋ณ์ ์ด๋ฆ๊ณผ ์ผ์นํด์ผ ํ๋ค.throwing์ ์ ์ง์ ๋ ํ์ ๊ณผ ๋ง๋ ์์ธ๋ฅผ ๋์์ผ๋ก ์คํํ๋ค.(๋ถ๋ชจ ํ์ ์ ์ง์ ํ๋ฉด ์์ ํ์ ๋ ์ธ์ )
@After
๋ฉ์๋ ์คํ์ด ์ข
๋ฃ๋๋ฉด ์คํ๋๋ค.(finally์ ๋น์ท)
@After(value = "Pointcuts.orderAndService()")
public void doAfter(JoinPoint joinPoint) {
    log.info("[after] {}", joinPoint.getSignature());
}์ ์ ๋ฐ ์์ธ ๋ฐํ ์กฐ๊ฑด์ ๋ชจ๋ ์ฒ๋ฆฌํ๋ค.
์ผ๋ฐ์ ์ผ๋ก ๋ฆฌ์์ค๋ฅผ ํด์ ํ๋ ๋ฐ ์ฌ์ฉํ๋ค.
@Around
๋ฉ์๋ ์คํ์ ์ฃผ๋ณ์์ ์คํ๋๋ค. ๋ฉ์๋ ์คํ ์ ํ์ ์์ ์ ์ํํ๋ค.
๊ฐ์ฅ ๊ฐ๋ ฅํ ์ด๋๋ฐ์ด์ค๋ค.
์กฐ์ธ ํฌ์ธํธ ์คํ ์ฌ๋ถ ์ ํ(
joinPoint.proceed()ํธ์ถ ์ฌ๋ถ ์ ํ)์ ๋ฌ ๊ฐ ๋ณํ(
joinPoint.proceed(args[]))๋ฐํ ๊ฐ ๋ณํ
์์ธ ๋ณํ
ํธ๋์ญ์  ์ฒ๋ผ
try~catch~finally๋ชจ๋ ๋ค์ด๊ฐ๋ ๊ตฌ๋ฌธ ์ฒ๋ฆฌ ๊ฐ๋ฅ
์ด๋๋ฐ์ด์ค์ ์ฒซ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ๋
ProceedingJoinPoint๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.proceed()๋ฅผ ํตํด ๋์์ ์คํํ๋ค.์ฌ๋ฌ ๋ฒ ์คํํ ์๋ ์๋ค.(์ฌ์๋)
## success() ์คํ ๊ฒฐ๊ณผ ์ฝ์
[around][ํธ๋์ญ์
 ์์] void hello.aop.order.OrderService.orderItem(String)
[before] void hello.aop.order.OrderService.orderItem(String)
[orderService] ์คํ
[orderRepository] ์คํ
[return] void hello.aop.order.OrderService.orderItem(String) return=null
[after] void hello.aop.order.OrderService.orderItem(String)
[around][ํธ๋์ญ์
 ์ปค๋ฐ] void hello.aop.order.OrderService.orderItem(String)
[around][๋ฆฌ์์ค ๋ฆด๋ฆฌ์ฆ] void hello.aop.order.OrderService.orderItem(String)
์คํ ์์:
@Around,@Before,@After,@AfterReturning,@AfterThrowing์ด๋๋ฐ์ด์ค๊ฐ ์ ์ฉ๋๋ ์์๋ ์ด๋ ์ง๋ง ํธ์ถ ์์์ ๋ฆฌํด ์์๋ ๋ฐ๋์ด๋ค.
@Aspect์์ ๋์ผํ ์ข ๋ฅ์ ์ด๋๋ฐ์ด์ค๊ฐ 2๊ฐ ์ด์ ์์ผ๋ฉด ์์๋ ๋ณด์ฅ๋์ง ์๋๋ค. ์ด ๊ฒฝ์ฐ@Aspect๋ฅผ ๋ณ๋ ํด๋์ค๋ก ๋ถ๋ฆฌํ๊ณ@Order๋ฅผ ์ ์ฉํด์ผ ํ๋ค.
@Around ์ธ์ ๋ค๋ฅธ ์ด๋๋ฐ์ด์ค๊ฐ ์กด์ฌํ๋ ์ด์
@Aroundํ๋๋ง ์์ด๋ ๋ค๋ฅธ ๋ชจ๋ ์ด๋๋ฐ์ด์ค์ ๊ธฐ๋ฅ์ ์ํํ ์ ์๋ค. ๊ทธ๋ฐ๋ฐ ๋ค๋ฅธ ์ด๋๋ฐ์ด์ค๋ค์ด ์กด์ฌํ๋ ์ด์ ๋ ๋ฌด์์ผ๊น?@Around๋ ํญ์joinPoint.proceed()๋ฅผ ํธ์ถํด์ผ ํ๋ค. ํธ์ถํ์ง ์์ผ๋ฉด ๋ค์ ํ์ผ์ด ํธ์ถ๋์ง ์๋๋ค. ํ์ง๋ง@Before๋joinPoint.proceed()๋ฅผ ์๋์ผ๋ก ํธ์ถํด ์ฃผ๊ธฐ ๋๋ฌธ์ ์๋ต์ด ๊ฐ๋ฅํ๋ค.
@Around๊ฐ ๊ฐ์ฅ ๋์ ๊ธฐ๋ฅ์ ์ ๊ณตํ์ง๋ง ์ค์ํ ๊ฐ๋ฅ์ฑ์ด ์๋ค. ๋ฐ๋ฉด์@Before,@After๊ฐ์ ์ด๋๋ฐ์ด์ค๋ ๊ธฐ๋ฅ์ ์ ์ง๋ง ์ค์ํ ๊ฐ๋ฅ์ฑ์ด ๋ฎ๊ณ ์ฝ๋๋ ๋จ์ํ๋ค. ๊ทธ๋ฆฌ๊ณ ๊ฐ์ฅ ์ค์ํ ์ ์ ์ด ์ฝ๋๋ฅผ ์์ฑํ ์๋๊ฐ ๋ช ํํ๊ฒ ๋๋ฌ๋๋ค๋ ์ ์ด๋ค.@Before๋ผ๋ ์ด๋ ธํ ์ด์ ์ ๋ณด๋ฉด ์ด ์ฝ๋๋ ํ๊ฒ ์คํ ์ ์ ํ์ ํด์ ์ด๋ค ์ผ์ ํ๋ ์ฝ๋๋ผ๋ ๊ฒ์ ๋ช ํํ๊ฒ ์ ์ ์๋ค๋ ๊ฒ์ด๋ค.์ข์ ์ค๊ณ๋ ์ ์ฝ์ด ์๋ ๊ฒ์ด๋ค.
@Around๋ฅผ ์ฌ์ฉํ๋๋ฐ ์ค์๋ก ๋ค์ ํ๊ฒ์ ํธ์ถํ์ง ์๋๋ค๋ฉด ํฐ ์ฅ์ ๊ฐ ์ผ์ด๋ ๊ฒ์ด๋ค. ์ฒ์๋ถํฐ@Before๊ฐ์ ํ์ ๋ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ค๋ฉด ์ด๋ฐ ๋ฌธ์  ์์ฒด๊ฐ ๋ฐ์ํ์ง ์์์ ๊ฒ์ด๋ค.์ ์ฝ ๋๋ถ์ ์ญํ ์ด ๋ช ํํด์ง๊ณ ์๋๋ ํ์ ํ๊ธฐ ์ฌ์์ง๋ค.
Last updated