hyeonga_code

Spring_AOP 심화 실습_4. 다양한 AOP 실습 본문

Spring

Spring_AOP 심화 실습_4. 다양한 AOP 실습

hyeonga 2024. 1. 9. 07:59
반응형


    - 글이 없는 경우 발생할 예외를 작성합니다.
- sts.spring.board.vo > ArticleNotFoundException.java 클래스 생성
=====

1
2
3
4
5
6
package sts.spring.board.vo;
 
public class ArticleNotFoundException extends Exception {
    private static final long serialVersionUID = 1L;
}
 




    - Read 서비스를 제공하는 인터페이스를 작성합니다.
- sts.spring.board.service > ReadArticleService.java 인터페이스 생성
=====

1
2
3
4
5
6
7
8
9
package sts.spring.board.service;
 
import sts.spring.board.vo.ArticleNotFoundException;
import sts.spring.board.vo.ArticleVO;
 
public interface ReadArticleService {
    ArticleVO getArticleAndIncreaseReadCount(int id) throws ArticleNotFoundException;
}
 



    - Read 서비스를 구현하는 클래스 작성
- sts.spring.board.service > ReadArticleServiceImpl.java 클래스 생성
=====

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package sts.spring.board.service;
 
import sts.spring.board.vo.ArticleNotFoundException;
import sts.spring.board.vo.ArticleVO;
 
public class ReadArticleServiceImpl implements ReadArticleService {
 
    @Override
    public ArticleVO getArticleAndIncreaseReadCount(int id) throws ArticleNotFoundException {
        if(id == 0)
            throw new ArticleNotFoundException();
        return new ArticleVO();
    }
}
 



- sts.spring.common > LoggingAdvice.java 클래스 생성
=====

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package sts.spring.common;
 
public class LoggingAdvice {
    
    public void before() {
        System.out.println("LogA >> Before method");
    }
    
    public void afterReturning(Object ret) {
        System.out.println("LogA >> After method [ return value : " + ret + "]");
    }
    
    public void afterThrowing(Throwable ex) {
        System.out.println("LogA >> During method exception [ exception : " + ex.getClass().getName() + "]");
    }
    
    public void afterFinally() {
        System.out.println("LogA >> Complete method");
    }
}
 




    - 실습용 캐시 서비스를 제공할 Advice 클래스를 작성합니다.
- sts.spring.common > ArticleCacheAdvice.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
package sts.spring.common;
 
import java.util.HashMap;
import java.util.Map;
 
import org.aspectj.lang.ProceedingJoinPoint;
 
import sts.spring.board.vo.ArticleVO;
 
public class ArticleCacheAdvice {
    
    private Map<Integer, ArticleVO> cache = new HashMap<Integer, ArticleVO>();
 
    // ArticleVO를 캐싱하는 메소드
    public ArticleVO cache(ProceedingJoinPoint joinPoint) throws Throwable {
        Integer id = (Integer) joinPoint.getArgs()[0];
        
        ArticleVO article = cache.get(id);
        
        if(article != null) {
            System.out.println("_ArticleCacheAdvice : Article[" + id + "]");
        }
        
        ArticleVO ret = (ArticleVO) joinPoint.proceed();
        
        if(ret != null) {
            cache.put(id, ret);
            System.out.println("_ArticleCacheAdvice : Article[" + id + "]");
        }
        return ret;
    }
}
 





    - 파라미터 접근 실습용 추적 정보 제공하는 Advice 클래스 작성하기
- sts.spring.common > UpdateMemberInfoTraceAdvice.java 클래스 생성
=====

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package sts.spring.common;
 
import org.aspectj.lang.JoinPoint;
 
import sts.spring.member.vo.UpdateInfo;
 
public class UpdateMemberInfoTraceAdvice {
 
    public void traceReturn(JoinPoint joinPoint, boolean result, String memberId, UpdateInfo info) {
        System.out.println("__TraceReturn___________");
        System.out.println("  - result : " + result);
        System.out.println("  - memberId : " + memberId);
        System.out.println("  - Updateinfo : " + info);
    }
}
 





- applicationContextTwo.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
29
30
31
32
33
34
35
36
<?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">
<!-- advice 빈을 등록합니다. -->
    <bean id="loggingAdvice" class="sts.spring.common.LoggingAdvice" />
    <bean id="cacheAdvice" class="sts.spring.common.ArticleCacheAdvice" />
    <bean id="traceAdvice" class="sts.spring.common.UpdateMemberInfoTraceAdvice" />
    
    <aop:config>
    <!-- 모든 public 메소드를 대상으로 적용하는 aspect입니다. -->
        <aop:aspect id="loggingAspect" ref="loggingAdvice" order="1">
            <aop:pointcut id="publicMethod" expression="execution(public * sts.spring..*(..))"/>
            <aop:before method="before" pointcut-ref="publicMethod" />
            <aop:after-returning method="afterReturning" pointcut-ref="publicMethod" returning="ret"/>
            <aop:after-throwing method="afterThrowing" pointcut-ref="publicMethod" throwing="ex" />
            <aop:after method="afterFinally" pointcut-ref="publicMethod" />
        </aop:aspect>
    
    <!-- ReadArticleServiceImpl의 모든 public 메소드를 대상으로 적용하는 aspect입니다. -->
        <aop:aspect id="cacheAspect" ref="cacheAdvice" order="2">
            <aop:around method="cache" pointcut="execution(public * *..ReadArticleServiceImpl.*(..))" />
        </aop:aspect>
    
    <!-- MemberService의 모든 public 메소드를 대상으로 적용하는 aspect입니다. -->    
        <aop:aspect id="traceAspect" ref="traceAdvice" order="3">
            <aop:after-returning method="traceReturn" pointcut="args(memberId, info)" returning="result" arg-names="joinPoint, result, memberId, info"/>
        </aop:aspect>
    </aop:config>
    
    <bean id="readArticleService" class="sts.spring.board.service.ReadArticleServiceImpl" />
    <bean id="memberService" class="sts.spring.member.service.MemberServiceImpl" />
</beans>
 




    - 테스트 할 메인 클래스를 작성합니다.
- sts.spring.board.controller > MainTwo.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
66
67
68
69
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 MainTwo {
    public static void main(String[] args) {
        
        // 컨테이너를 생성합니다.
        String[] configLocations = new String[] { "applicationContextTwo.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("javaline"new UpdateInfo());
        
        context.close();
            /*
                LogA >> Before method
                _ArticleCacheAdvice : Article[1]
                LogA >> After method [ return value : sts.spring.board.vo.ArticleVO@45a37759]
                LogA >> Complete method
                LogA >> Before method
                _ArticleCacheAdvice : Article[1]
                _ArticleCacheAdvice : Article[1]
                LogA >> After method [ return value : sts.spring.board.vo.ArticleVO@63611043]
                LogA >> Complete method
                article1 == article2 : false
                LogA >> Before method
                LogA >> During method exception [ exception : sts.spring.board.vo.ArticleNotFoundException]
                LogA >> Complete method
                LogA >> Before method
                + MemberServiceImpl.update()
                __TraceReturn___________
                  - result : true
                  - memberId : javaline
                  - Updateinfo : sts.spring.member.vo.UpdateInfo@3f57bcad
                LogA >> After method [ return value : true]
                LogA >> Complete method
             */
    }
}
 

 

반응형