티스토리 뷰
AOP 실습 및 테스트
AOP실습을 위해 Spring Legacy Project 생성
1.프로젝트에 패키지를 생성하고 테스트를 위한 Service Interface와 Class 구현
SampleService 인터페이스 내용
package org.sample.service; public interface SampleService { public Integer doAdd(String str1, String str2) throws Exception; }
SampleServiceImpl 클래스
package org.sample.service; import org.springframework.stereotype.Service; @Service public class SampleServiceImpl implements SampleService { @Override public Integer doAdd(String str1, String str2) throws Exception { // TODO Auto-generated method stub return Integer.parseInt(str1) + Integer.parseInt(str2); } }
2.Advice 작성
AOP를 사용하지 않았을 때는 Service클래스 내에 logging을 위한 코드를 직접 넣었는데, AOP를 사용하면서 실제 Service의 기능들만 구현하고, 핵심로직은아니지만 필요한, 반복적인 기능은 Advice에 구현.
aop패키지를 생성하고 여기에 LogAdvice 클래스를 추가
LogAdvice 클래스
package org.sample.aop; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; import lombok.extern.log4j.Log4j; @Aspect @Log4j @Component public class LogAdvice { @Before( "execution(* org.sample.service.SampleService*.*(..))") public void logBefore() { log.info("=================================================="); } }
"execution(* org.sample.service.SampleService*.*(..))"
는 어떤 위치에 Advice를 적용할 것인지를 결정해주는 PointCut
3.args를 이용한 파라미터 추적
LogAdvice에 PointCut 설정 할 때 args를 이용하면, 간단히 파라미터를 구현할 수 있다
@Before( "execution(* org.sample.service.SampleService*.doAdd(String, String)) && args(str1, str2)") public void logBeforeWithParam(String str1, String str2) { log.info("str1 : " + str1); log.info("str2 : " + str2); }
excution으로 시작하는 PointCut설정에 doAdd()메서드를 명시하고, 파라미터 타입을 지정.
&& args부분에 변수명을 지정했는데, 이 정보를 이용해서 해당 메서드의 파라미터를 설정
4.@AfterThrowing
파라미터의 값이 잘못되서 예외가 발생하는 경우가 있는데, AOP의 @AfterThrowing 어노테이션은, 지정된 대상이 예외를 발생한 후에 동작하면서 문제를 찾을 수 있다
@AfterThrowing(pointcut = "execution(* org.sample.service.SampleService*.*(..))", throwing = "exception") public void LogException(Exception exception) { log.info("Exception!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); log.info("exception : " + exception); }
5.@Around와 ProceedingJoinPoint
AOP를 이용해 더 구체적인 처리를 하려면, @Arount, ProceedingJoinPoint를 이용하면 된다.
@Arount는 직접 대상메서드를 실행할 수 있는 권한을 가지고있고, 메서드의 실행 전과 후에 처리가 가능하다.
ProceedingJoinPoint는 @Around와 같이 결합해서 파라미터나, 예외등을 처리할 수 있다.
@Around("execution(* org.sample.service.SampleService*.*(..))") public Object logTime(ProceedingJoinPoint pjp) { long start = System.currentTimeMillis(); log.info("Target : " + pjp.getTarget()); log.info("Param : " + Arrays.deepToString(pjp.getArgs())); Object result = null; try { result = pjp.proceed(); } catch (Throwable e) { // TODO: handle exception e.printStackTrace(); } long end = System.currentTimeMillis(); log.info("TIME : " + (end - start)); return result; }
- logTime()의 PointCut설정은
...SampleService*.*
로 지정. - ProceedingJoinPoint는 AOP대상이 되는 Target이나, 파라미터등을 파악하고 직접 실행을 결정할 수도 있다.
- @Around가 적용되는 메서드의 경우에는, 리턴타입이 void가 아닌타입으로 설정해야하고, 메서드의 실행결과도 반환하는 형태로 작성해야 된다.
- logTime()의 PointCut설정은
출처 : 코드로 배우는 스프링 웹 프로젝트
'Spring boot study > 5. AOP' 카테고리의 다른 글
AOP 적용을 위한 설정. (0) | 2020.08.07 |
---|---|
AOP 용어 정리 (0) | 2020.08.04 |