최신글
hyeonga_code
Spring_AOP 심화 실습_@Aspect 어노테이션 활용한 다양한 Advice 적용 본문
반응형
- 포인트 컷 클래스 작성하기
- @Pointcut 어노테이션
- Pointcut을 정의하는 AspectJ 표현식의 값을 가집니다.
- 적용한 메소드는 void 리턴 타입을 가집니다.
- Advice 관련 어노테이션에서 해당 메소드 이름을 이요하여 pointcut을 사용할 수 있습니다.
- sts.spring.common > PublicPointcut.java 클래스 생성
=====
1
2
3
4
5
6
7
8
9
10
|
package sts.spring.common;
import org.aspectj.lang.annotation.Pointcut;
public class PublicPointcut {
@Pointcut("execution(public * sts.spring..*Impl.*(..))")
public void publicMethod() {}
}
|
- 로그인 서비스를 제공하는 Aspect 클래스를 작성합니다.
- sts.spring.common > LoggingAsepct.java 클래스 생성
=====
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
29
30
31
32
33
34
|
package sts.spring.common;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
@Aspect
@Order(1)
public class LoggingAspect {
@Before("PublicPoint.publicMethod()")
public void before() {
System.out.println("LogAs>> Before method");
}
@AfterReturning(pointcut = "sts.spring.common.PublicPointcut.publicMethod()", returning="ret")
public void afterReturning(Object ret) {
System.out.println("LogAs>> After method [return value : " + ret + "]");
}
@AfterThrowing(pointcut = "sts.spring.common.PublicPointcut.publicMethod()", throwing="ex")
public void afterThrowing(Throwable ex) {
System.out.println("LogAs>> During method exception [ exception : " + ex.getClass().getName() + "]");
}
@After("sts.spring.common.PublicPointcut.publicMethod()")
public void afterFinally() {
System.out.println("LogAs>> Complete method");
}
}
|
- 캐시 서비스를 제공하는 Aspect 클래스를 작성합니다.
- sts.spring.common > ArticleCacheAspect.java 클래스 생성
=====
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
package sts.spring.common;
import java.util.HashMap;
import java.util.Map;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.Ordered;
import sts.spring.board.vo.ArticleVO;
@Aspect
public class ArticleCacheAspect implements Ordered {
// 결과를 캐싱하기 위해 사용합니다.
private Map<Integer, ArticleVO> cache = new HashMap<Integer, ArticleVO>();
// *..ReadArticleService 패키지 내의 모든 public 메소드에 적용됩니다.
@Around("execution(public * *..ReadArticleService.*(..))")
public ArticleVO cache(ProceedingJoinPoint joinPoint) throws Throwable{
// 첫 번째 매개 변수를 추출하여 id 로 사용합니다.
Integer id = (Integer) joinPoint.getArgs()[0];
// id를 사용하여 게시물 데이터를 찾아옵니다.
ArticleVO article = cache.get(id);
// 게시물이 있는 경우 캐시 데이터에 추가하고 데이터를 반환합니다.
if(article != null) {
System.out.println("_ArticleCacheAspect : Article[" + id + "]");
return article;
}
// 게시물이 없는 경우 원래 메소드를 실행하여 결과를 ret에 저장합니다.
ArticleVO ret = (ArticleVO) joinPoint.proceed();
// 실행된 경우 게시물 데이터를 캐시에 추가하여 반환합니다.
if(ret != null) {
cache.put(id, ret);
System.out.println("_ArticleCacheAspect : Article[" + id + "]");
}
return ret;
}
@Override
public int getOrder() {
return 2;
}
}
|
- 회원 정보를 변경하고 추적 서비스를 제공하는 Aspect 클래스를 작성하기
- sts.spring.common > UpdateMemberInfoTraceAspect.java 클래스 생성
=====
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package sts.spring.common;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import sts.spring.member.vo.UpdateInfo;
@Aspect
@Order(3)
public class UpdateMemberInfoTraceAspect {
@AfterReturning(pointcut = "args(memberId, info)", returning="result", argNames="result, memberId, info")
public void traceReturn(JoinPoint joinPoint, boolean result, String memberId, UpdateInfo info) {
System.out.println("__TraceAspect Return___________");
System.out.println(" - result : " + result);
System.out.println(" - memberId : " + memberId);
System.out.println(" - Updateinfo : " + info);
}
}
|
- applicaionContextFour.xml 파일 생성
=====
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<?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: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/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<aop:aspectj-autoproxy />
<bean id="traceAspect" class="sts.spring.common.UpdateMemberInfoTraceAspect" />
<bean id="cacheAspect" class="sts.spring.common.ArticleCacheAspect" />
<bean id="loggingAspect" class="sts.spring.common.LoggingAspect" />
<bean id="readArticleService" class="sts.spring.board.service.ReadArticleServiceImpl" />
<bean id="memberService" class="sts.spring.member.service.MemberServiceImpl" />
</beans>
|
- 테스트 클래스를 작성합니다.
- sts.spring.board.controller > MainFour.java 클래스 생성
====
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
package sts.spring.board.controller;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import sts.spring.board.service.ReadArticleService;
import sts.spring.board.vo.ArticleNotFoundException;
import sts.spring.board.vo.ArticleVO;
import sts.spring.member.vo.MemberService;
import sts.spring.member.vo.UpdateInfo;
public class MainFour {
public static void main(String[] args) {
String[] configLocations = new String[] { "applicationContextFour.xml" };
AbstractApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
ReadArticleService readArticleService = context.getBean("readArticleService", ReadArticleService.class);
try {
// 1번글을 얻어와 캐시에 저장합니다.
ArticleVO article1 = readArticleService.getArticleAndIncreaseReadCount(1);
// 캐시에 저장되어 있던 1번 글을 가져옵니다.
ArticleVO article2 = readArticleService.getArticleAndIncreaseReadCount(1);
// 값이 같은 경우 : 캐시에 넣은 값을 가져오는 것입니다.
System.out.println("article1 == article2 : " + (article1 == article2));
// 0번 글은 얻어올 수 없으므로 예외 처리를 확인할 수 있습니다.
readArticleService.getArticleAndIncreaseReadCount(0);
} catch(ArticleNotFoundException e) { }
MemberService memberService = context.getBean("memberService", MemberService.class);
memberService.update("name01", new UpdateInfo());
context.close();
/*
LogAs>> Before method
_ArticleCacheAspect : Article[1]
LogAs>> After method [return value : sts.spring.board.vo.ArticleVO@6c2ed0cd]
LogAs>> Complete method
LogAs>> Before method
_ArticleCacheAspect : Article[1]
LogAs>> After method [return value : sts.spring.board.vo.ArticleVO@6c2ed0cd]
LogAs>> Complete method
article1 == article2 : true
LogAs>> Before method
LogAs>> During method exception [ exception : sts.spring.board.vo.ArticleNotFoundException]
LogAs>> Complete method
LogAs>> Before method
+ MemberServiceImpl.update()
__TraceAspect Return___________
- result : true
- memberId : name01
- Updateinfo : sts.spring.member.vo.UpdateInfo@36a5cabc
LogAs>> After method [return value : true]
LogAs>> Complete method
*/
}
}
|
반응형
'Spring' 카테고리의 다른 글
[JAVA/SPRING] 포트원/아임포트 결제 적용 IamportResponse<Payment> (0) | 2024.02.15 |
---|---|
@PostConstruct 어노테이션 (0) | 2024.02.15 |
Spring_AOP 심화 실습_5. 어노테이션 활용하기 (0) | 2024.01.09 |
Spring_AOP 심화 실습_4. 다양한 AOP 실습 (1) | 2024.01.09 |
Spring_AOP 심화 실습_ 3. XML 설정 이용하기 (0) | 2024.01.08 |