Spring AOP

김덕근·2023년 5월 12일
0

Spring

목록 보기
19/19

Advice + Pointcut = Aspect


pom.xml

AspectJ Runtime » 1.9.4
AspectJ Weaver » 1.9.4

servlet-context.xml

<!-- aop auto proxy -->
<aop:aspectj-autoproxy proxy-target-class="false"/>

proxy-target-class

프록시가 적용될 클래스가

인터페이스면 false

-> Spring AOP는 기본적으로 인터페이스를 상속 받은 프록시가 생성되어 코드를 수행함

일반클래스면 true

-> cglib 라이브러리를 이용해서 일반 클래스를 상속받아 프록시 생성


설정

Servers(Overview) -> Open launch configuration -> Arguments ->
VM arguments: -> space 한번 추가, -Djava.net.preferIPv4Stack=true 입력


@Component

런타임시 필요한 위치에 코드를 알아서 참여시킬 수 있도록 bean 등록

@Aspect

공통 관심사(특정 흐름 사이에 끼여서 수행할 코드)가 작성된 클래스임을 명시
-> 해당 어노테이션이 작성된 클래스에는
advice(끼여들어서 수행할 메서드)
pointcut(advice 끼여들어서 수행될 부분)이 작성되어 있어야 한다.

@Before("execution(* edu.kh.comm.member..*Impl.*(..))")

@Before("CommonPointcut.implPointcut()")

@After("memberPointcut()")

@After("CommonPointcut.implPointcut()")

@AfterReturning

기존 @After + 반환값 얻어오기 기능

@Pointcut

-> Pointcut의 패턴이 작성되는 부분에 memberPointcut 메서드 이름을 작성하면
@Pointcut에 작성된 패턴이 적용된다.
@Pointcut("execution( edu.kh.comm.member..Impl.*(..))")
public void memberPointcut() {}


common.aop.CommonPointcut.java

public class CommonPointcut {
	// 회원 서비스용 Pointcut
		@Pointcut("execution(* edu.kh.comm.member..*Impl.*(..))")
		public void memberPointcut() {} 
		
		// 모든 ServiceImpl 클래스용 Pointcut
		@Pointcut("execution(* edu.kh.comm..*Impl.*(..))")
		public void implPointcut() {}
}

public class AfterReturningAspect {
	private Logger logger = LoggerFactory.getLogger(BeforeAspect.class);
	
	// @AfterReturning : 기존 @After + 반환값 얻어오기 기능
	
	@AfterReturning(pointcut = "CommonPointcut.implPointcut()", returning = "returnObj")
	public void serviceReturnValue(JoinPoint jp, Object returnObj) {

		logger.info("Return Value : " + returnObj);
		
	}
}

JoinPoint 인터페이스

advice가 적용되는 Target Object (ServiceImpl)의 정보, 전달되는 매개변수, 메서드, 반환값, 예외 등 얻을 수 있는 메서드를 제공

(주의사항) JoinPoint 인터페이스는 항상 첫 번째 매개변수로 작성되어야 한다!


....common.aop.AroundAspect.java

실행시간(runingTime) 을 확인하기위한 Aspect

@Component
@Aspect
@Order(4) // 숫자가 높을수록 선 실행
public class AroundAspect {
	private Logger logger = LoggerFactory.getLogger(BeforeAspect.class);
	
	// @Around : 전처리(@Before)와 후처리(@After)를 한번에 작성 가능한 advice
	@Around("CommonPointcut.implPointcut()")
	public Object runingTime(ProceedingJoinPoint jp) throws Throwable {
		// proceed() 메소드 호출 전  : @Before advice 작성
		// proceed() 메소드 호출 후  : @After advice 작성
		// 메소드 마지막에 proceed()의 반환값을 리턴해야함.
		
		// System.currentTimeMillis() :
		// 1970/01/01 오전 9시 (한국 OS 기준) 부터
		// 지금까지 지난 시간을 ms 단위로 나타낸 값 
		
		long startMs = System.currentTimeMillis();
		Object obj = jp.proceed(); // 전/후 처리를 나누는 기준
		long endMs = System.currentTimeMillis();
		logger.info("Running Time : " + (endMs - startMs) + "ms");
        
		return obj;	
	}
}
profile
안녕하세요!

0개의 댓글