spring
day2 class05 어노테이션 기반 AOP
일상다반ㅅㅏ
2019. 1. 6. 21:00
1. 어노테이션 기반 AOP 설정
- <aop:aspectj-autoproxy/> 엘리먼트만 선언하면 스프링 컨테이너는 AOP 관련 어노테이션들을 인식하고 용도에 맞게 처리해준다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <!-- applicationContext.xml --> <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd"> <context:component-scan base-package="com.springbook.biz"></context:component-scan> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans> | cs |
2. Before 어드바이스
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @Service @Aspect // Aspect = Pointcut + Advice public class BeforeAdvice { // Pointcut @Pointcut("execution(* com.springbook.biz..*Impl.*(..))") public void allPointcut() {} // Advice @Before("allPointcut()") public void beforeLog(JoinPoint jp) { String method = jp.getSignature().getName(); Object[] args = jp.getArgs(); System.out.println("[사전 처리] " + method + "() 메소드 ARGS 정보 : " + args[0].toString()); } } | cs |
3. After Returning 어드바이스
- 메소드 수행 결과를 받아내기 위해 포인트컷을 참조하는 속성과 바인드 변수를 사용한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | @Service @Aspect public class AfterReturningAdvice { @Pointcut("execution(* com.springbook.biz..*Impl.get*(..))") public void getPointcut() {} @AfterReturning(pointcut="getPointcut()", returning="returnObj") public void afterLog(JoinPoint jp, Object returnObj) { String method = jp.getSignature().getName(); if(returnObj instanceof UserVO) { UserVO user = (UserVO) returnObj; if(user.getRole().equals("Admin")) { System.out.println(user.getName() + " 로그인(Admin)"); } } System.out.println("[사후 처리] " + method + "() 메소드 리턴값 : " + returnObj.toString()); } } | cs |
4. After Trhowing 어드바이스
- 비즈니스 메소드에서 발생된 예외 객체를 받아낼 수 있도록 포인트컷을 참조하는 속성과 바인드 변수를 사용한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @Service @Aspect public class AfterThrowingAdvice { @Pointcut("execution(* com.springbook.biz..*Impl.*(..))") public void allPointcut() {} @AfterThrowing(pointcut="allPointcut()", throwing="exceptObj") public void exceptionLog(JoinPoint jp, Exception exceptObj) { String method = jp.getSignature().getName(); System.out.println(method + "() 비즈니스 로직 수행 중 예외 발생!"); if(exceptObj instanceof IllegalArgumentException) { System.out.println("부적합한 값이 입력되었습니다."); } else if(exceptObj instanceof NumberFormatException) { System.out.println("숫자 형식의 값이 아닙니다."); } else if(exceptObj instanceof Exception) { System.out.println("문제가 발생했습니다."); } } } |
5. After 어드바이스
1 2 3 4 5 6 7 8 9 10 11 12 | @Service @Aspect public class AfterAdvice { /*@Pointcut("execution(* com.springbook.biz..*Impl.*(..))") public void allPointcut() {}*/ @After("allPointcut()") public void finallyLog() { System.out.println("[사후 처리] 비즈니스 로직 수행 후 무조건 동작"); } } | cs |
6. Around 어드바이스
- Around는 proceed를 사용하기 위해 ProceedingJoinPoint를 사용한다는 것을 다시 한번 강조한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | @Service @Aspect public class AroundAdvice { /*@Pointcut("execution(* com.springbook.biz..*Impl.*(..))") public void allPointcut() {}*/ @Around("allPointcut()") public Object aroundLog(ProceedingJoinPoint pjp) throws Throwable { String method = pjp.getSignature().getName(); StopWatch stopWatch = new StopWatch(); stopWatch.start(); Object returnObj = pjp.proceed(); stopWatch.stop(); System.out.println(method + "() 메소드 수행에 걸린 시간 : " + stopWatch.getTotalTimeMillis() + "(ms)초"); return returnObj; } } | cs |
7. 외부 Pointcut 참조하기
- xml 설정으로 포인트컷을 관리했을 때는 포인트컷을 여러개 등록하여 재사용할 수 있었다.
- 어노테이션 설정을 하면 클래스 마다 반복 선언이 되었기 때문에 이를 해결하기 위해 공통 클래스로 등록한다.
- 어드바이스 클래스에서는 포인트컷 함수를 삭제하고 포인트컷 함수의 경로를 지정해준다.
1 2 3 4 5 6 7 8 9 | @Aspect public class PointcutCommon { @Pointcut("execution(* com.springbook.biz..*Impl.*(..))") public void allPointcut() {} @Pointcut("execution(* com.springbook.biz..*Impl.get*(..))") public void getPointcut() {} } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @Service @Aspect public class BeforeAdvice { /*@Pointcut("execution(* com.springbook.biz..*Impl.*(..))") public void allPointcut() {}*/ @Before("PointcutCommon.allPointcut()") public void beforeLog(JoinPoint jp) { String method = jp.getSignature().getName(); Object[] args = jp.getArgs(); System.out.println("[사전 처리] " + method + "() 메소드 ARGS 정보 : " + args[0].toString()); } } | cs |