본문 바로가기

프로그래밍/Spring

[Spring]AOP : XML 스키마 사용, 어노테이션 사용

AOP

- 공통 관심 사항을 구현한 코드를 핵심 로직을 구현한 코드안에 삽입하는 것을 의미

- 어노테이션을 이용하여 AOP 구현 시, @Aspect 어노테이션을 사용하고

- xml 설정파일에 <aop:aspectj-autoproxy/> 명시해야한다.

Advice 언제 공통 관심 기능을 핵심 로직에 적용할 지를 정의
Joinpoint Advice를 적용 가능한 지점을 의미
Weaving Advice를 핵심 로직 코드에 적용 하는 것
Pointcut Joinpoint의 부분 집 합으로 실제 Advice가 적용되는 Joinpoint를 나타낸다.
Aspect 여러 객체에 공통으로 적용되는 공통 관심 사항

 

Advice 종류

종류 설명
Before Advice
@Before
대상 객체의 메서드 호출 전에 공통 기능을 실행
After Returning Advice
@AfterReturning
대상 객체의 메서드가 예외 없이 실행한 이후에 공통 기능을 실행
After Throwing Advice
@AfterThrowing
대상 객체의 메서드를 실행하는 도중 예외가 발생한 경우에 공통 기능을 실행
After Advice
@After
대상 객체의 메서드를 실행하는 도중 예외가 발생했는지의 여부와 상관없이 메서드
실행 후 공통 기능을 실행(try~catch문의 finally 블럭과 비슷)
Around Advice
@Around
대상 객체의 메서드 실행 전, 후 또는 예외 발생 시점에 공통 기능을 실행하는데 사용

 

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
37
38
39
40
41
42
43
public class MyFirstAdvice {
    public void before() {
        //메서드 시작 직전에 동작하는 어드바이스
        System.out.println("Hello Before! **메서드가 호출되기 전에 나온다!");
    }
    
    public void  afterReturning(String msg) {
        //메서드 호출이 예외를 내보내지 않고 종료했을 때 동작하는 어드바이스
        System.out.println("Hello AfterReturning **메서드가 호출한 후에 나온다! 전달된 객체 : "+msg);
    }
    
    public void afterThrowing(Throwable ex) {
        //메서드 호출이 예외를 던졌을 때 동작하는 어드바이스
        System.out.println("Hello AfterThrowing **예외가 생기면 나온다! 예외 : "+ex);
    }
    
    public void after() {
        //예외가 발생해도 실행됨
        //메서드 종료 후에 동작하는 어드바이스
        System.out.println("Hello After **메서드가 호출된 후에 나온다!");
    }
    
    public String around(ProceedingJoinPoint joinPoint) throws Throwable{
        //메서드 호출 전 후에 동작하는 어드바이스
        System.out.println("Hello Around before! **메서드가 호출되기 전에 나온다!");
        String s = null;
        /*
         * try~catch~finally 구조로 명시해야 예외가 발생해도 메서드 실행 후 공통 기능을 수행
         */
        try {
            //핵심기능이 수행된 후 데이터 반환
            s = (String)joinPoint.proceed();
            
        }catch(Exception e) {
            e.printStackTrace();
        }finally {
            System.out.println("Hello Around after! **메서드가 호출된 후에 나온다! 반환된 객체 : " + s);
        }
        
        return s;
    }
    
}
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 <!-- 공통 기능을 가지고 있는 클래스 빈 객체 설정 -->
   <bean id="myFirstAdvice" class="kr.spring.ch01.MyFirstAdvice"/>
   
   <!-- 핵심 기능을 가지고 있는 클래스 빈 객체 설정 -->
   <bean id="product" class="kr.spring.product.Product"/>
   
   <!-- AOP 설정 -->
   <aop:config>
        <!-- 공통 기능을 가지고 있는 빈 객체 등록 -->
        <aop:aspect id="aspect" ref="myFirstAdvice">
            <!-- 핵심 기능 검색 -->
            <aop:pointcut expression="execution(public String launch())" id="publicMethod"/>
            <!-- 공통 기능을 적용할 시점 설정 -->
            <aop:before method="before" pointcut-ref="publicMethod"/>
            <aop:after-returning method="afterReturning" pointcut-ref="publicMethod" returning="msg"/> 
            <aop:after-throwing method="afterThrowing" pointcut-ref="publicMethod" throwing="ex"/>
            <aop:after method="after" pointcut-ref="publicMethod"/>
            <aop:around method="around" pointcut-ref="publicMethod"/>
        </aop:aspect>
   </aop:config>
cs

 

어노테이션을 이용한 AOP 설정 예시

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
@Aspect
public class MyFirstAdvice {
 
    //핵심 기능 검색
    @Pointcut("execution(public String launch())")
    public void getPointcut() {
        
    }
    //@Before("getPointcut()")
    public void before() {
        //메서드 시작 직전에 동작하는 어드바이스
        System.out.println("Hello Before! **메서드가 호출되기 전에 나온다!");
    }
    
    //@AfterReturning(value="getPointcut()",returning = "msg")
    public void  afterReturning(String msg) {
        //메서드 호출이 예외를 내보내지 않고 종료했을 때 동작하는 어드바이스
        System.out.println("Hello AfterReturning **메서드가 호출한 후에 나온다! 전달된 객체 : "+msg);
    }
    
    //@AfterThrowing(value="getPointcut()", throwing = "ex")
    public void afterThrowing(Throwable ex) {
        //메서드 호출이 예외를 던졌을 때 동작하는 어드바이스
        System.out.println("Hello AfterThrowing **예외가 생기면 나온다! 예외 : "+ex);
    }
    
    //@After("getPointcut()")
    public void after() {
        //예외가 발생해도 실행됨
        //메서드 종료 후에 동작하는 어드바이스
        System.out.println("Hello After **메서드가 호출된 후에 나온다!");
    }
    
    @Around("getPointcut()")
    public String around(ProceedingJoinPoint joinPoint) throws Throwable{
        //메서드 호출 전 후에 동작하는 어드바이스
        System.out.println("Hello Around before! **메서드가 호출되기 전에 나온다!");
        String s = null;
        /*
         * try~catch~finally 구조로 명시해야 예외가 발생해도 메서드 실행 후 공통 기능을 수행
         */
        try {
            //핵심기능이 수행된 후 데이터 반환
            s = (String)joinPoint.proceed();
            
        }catch(Exception e) {
            e.printStackTrace();
        }finally {
            System.out.println("Hello Around after! **메서드가 호출된 후에 나온다! 반환된 객체 : " + s);
        }
        
        return s;
    }
    
}
cs
1
2
3
4
5
6
7
8
  <!-- 공통 기능을 가지고 있는 클래스 빈 객체 설정 -->
   <bean id="myFirstAdvice" class="kr.spring.ch02.MyFirstAdvice"/>
   
   <!-- 핵심 기능을 가지고 있는 클래스 빈 객체 설정 -->
   <bean id="product" class="kr.spring.product.Product"/>
   
     <!-- 어노테이션 방식으로 AOP 구현할 때 명시 -->
     <aop:aspectj-autoproxy/>
cs