2020. 9. 24. 17:14ㆍ개발공부/Spring
Interface를 이용한 자동 메서드 주입은 AOP를 몰랐기 때문에 제가 붙인 풀어서 쓴 이름이고 AOP에 대해 이어서 얘기해보겠습니다. 개발할 때 중복이 많다면 좋은 코드가 아니라고 합니다. 흔히 클린코드의 특성 중 하나도 중복성 최소화가 포함됩니다. 따라서 아노테이션과 XML 파일을 사용해 AOP 구현방법을 이전 글에서 다루어 보았는데 연장되는 내용으로 스프링의 추가 기능 @Pointcut이 있습니다.
pointcut 지정 아노테이션 @Pointcut
해당 아노테이션을 사용하면 말이죠 핵심 메서드의 경로를 공통 메서드에 일일이 쳐넣을 필요가 없습니다. 단 @Pointcut를 선언한 메서드를 담아주기만 하면 될 뿐. 말로 설명하는 것보다 바로 코드를 보시죠.
보시면 @Before() 괄호 내에 일일이 쳐줬던 "execution( * runSomething())" 핵심 메서드 경로를 @Pointcut에 한 번만 설정해주면 생성하는 공통 메서드 매개변수론 지시자(메서드)명만 써주면 된다는 사실입니다. 그럼 XML 파일에선 어떻게 구현하는지도 볼까요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
package aop006;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect //이 클래스는 AOP에서 사용할 관점(횡단관심기능이 들어 있다.)
public class MyAspect {
//중복을 해결해주는 아노테이션 - 포인트컷 지시자를 미리 설정해두는 것
@Pointcut("execution(* runSomething())")
private void pointcut() {}
@Before("pointcut()")
public void before(JoinPoint joinPoint) {
System.out.println("열쇠로 문을 열고 집에 들어간다.");
}
@After("pointcut()")
public void after(JoinPoint joinPoint) {
System.out.println("외출 시 문을 잠근다.");
}
}
|
cs |
pointcut 지정 XML 형식 JSTL
긴말이 필요없습니다. <aop: pointcut expression="" id=""/>
JSTL을 이용해줬습니다. 단, before와 after 부분에서 pointcut-ref로 pointcut 'id'를 입력해줘야 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
<?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: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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
<aop:aspectj-autoproxy/>
<bean id = "myAspect" class="aop007.MyAspect"/>
<bean id = "boy" class="aop007.Boy"/>
<aop:config>
<aop:pointcut expression="execution(* runSomething())" id="pntcut"/>
<aop:aspect ref="myAspect">
<aop:before method="before" pointcut-ref="pntcut"/>
<aop:after method="after" pointcut-ref="pntcut"/>
</aop:aspect>
</aop:config>
</beans>
|
cs |
주입 시점이 다른 Around, After-Returning, After-Throwing
앞서 @Before와 @After는 핵심 메서드 '실행 전', '실행 후'에 들어가는 아노테이션이었습니다. 이 둘 외에도 실행 시점을 지정할 수 있는 아노테이션이 있는데요, 바로 @Around, @AfterReturning, @After-Throwing입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
@Around("execution(* runSomething())")
public void around(ProceedingJoinPoint pjp) {
//ProceedingJoinPoint: 핵심 기능을 호출하는 기능을 가지고 있음(around 사용 시 필수!)
//before
System.out.println("옷을 갈아입는다.");
try {
pjp.proceed(); //핵심 기능 호출 == (이전예제) delegate.factorial(20);
} catch (Throwable e) {
e.printStackTrace();
}
//after
System.out.println("씻는다.");
}
@AfterReturning("execution(* runSomething())")
public void afterReturning(JoinPoint jp) {
System.out.println("핵심기능 정상 종료: 하루를 반성");
}
@AfterThrowing("execution(* runSomething())")
public void afterThrowing(JoinPoint jp) {
System.out.println("119에 신고!");
}
|
cs |
@Around
핵심 메서드와 공통 메서드의 실행 시점을 자유롭게 설정할 수 있는 Around 아노테이션은 단독적으로 지시자(메서드)의 매개 변수를 JoinPoint가 아닌 ProceedingJoinPoint를 사용합니다. 해당 API의 .proceed() 메서드는 핵심 메서드를 호출하는 기능이 있습니다. 따라서 try-catch로 핵심 메서드를 선언해주고 원하는 위치에 공통 메서드를 놓아주면 됩니다.
@AfterReturning
핵심 메서드가 종료됐을 때 조건없이 공통 메서드를 실행하는 기능이 @After라면 반드시 핵심 메서드 호출이 성공했을 때 반환하는 메서드일 때 @AfterReturning을 사용합니다. 만약 에러(Exception)이 발생했다면 실행되지 않습니다. 따라서 실행시점은 핵심 메서드가 호출된 후 입니다.
@AfterThrowing
반대로 예외가 발생했을 때만 실행되는 공통 메서드를 지정해주려면 @AfterThrowing을 사용하면 됩니다. 예제에서는 예외가 "불이 남"이었기 때문에 실행되는 메서드에 "119에 신고!"라고 쓰여 있습니다. 핵심 기능 예외를 인지했을 때 실행되기 때문에 실행시점은 예외 syntax가 출력되기 전입니다.
'개발공부 > Spring' 카테고리의 다른 글
[Spring] MVC 웹페이지 구현 - Eclipse & xml 설정 (0) | 2020.10.07 |
---|---|
[Spring] AOP ④ - (예제) HashMap으로 Cache 기능구현 (0) | 2020.09.30 |
[Spring] Interface를 활용한 자동 메서드 실행 ② AOP (0) | 2020.09.24 |
[Spring] Interface를 활용한 자동 메서드 실행 ① (0) | 2020.09.22 |
[Spring] bean 객체의 생애 (0) | 2020.09.22 |