프로그래밍/Spring

스프링(Spring) - AOP 개념과 예제 - @Aspect 구현

abfc 2016. 11. 8.
반응형

예제파일 : 

aopEx2.zip


관련포스팅 : 스프링(Spring) - AOP 개념과 예제 - XML 기반으로 구현


안녕하세요. 이전 포스팅에 이어서 @Aspect를 이용한 AOP를 설정해보도록 하겠습니다.

내용은 이전 포스팅과 동일합니다.



aopEx2/src/main/java/com/aopEx2/LogAop.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
package com.aopEx2;
 
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
 
@Aspect //Aspect 역할을 할 클래스라고 명시해줌
public class LogAop {
 
    //Pointcut이라고 명시된 메서드가 필요
    //@Pointcut의 속성에 핵심코드의 어느 부분까지 공통기능을 사용하겠다고 명시
    @Pointcut("within(com.aopEx2.*)")
    private void pointcutMethod(){ 
        
    }
    
    @Around("pointcutMethod()"//around가 적용될 포인트컷을 명시 : pointcutMethod()
    public Object loggerAop(ProceedingJoinPoint joinpoint) throws Throwable{
        
        //공통 기능이 적용되는 메서드가 어떤 메서드인지 출력하기 위해 메서드명을 얻어옴
        String signatureStr = joinpoint.getSignature().toShortString();
        System.out.println(signatureStr + "시작"); //메서드 실행
        
        //공통기능
        System.out.println("핵심 기능 전에 실행 할 공통 기능입니다. "+System.currentTimeMillis());
        
        try {
            Object obj = joinpoint.proceed(); //핵심 기능 실행
            return obj;
        } finally {
            //공통기능
            System.out.println("핵심 기능 후에 실행 할 공통 기능입니다. "+System.currentTimeMillis());
            
            System.out.println(signatureStr + "끝");
        }
    }
    
    @Before("within(com.aopEx2.*)")
    public void beforeMethod(){
        System.out.println("beforeMethod()실행");
    }
}
 
cs


주석으로 설명을 써놨는데요. @Pointcut을 사용하지 않으셔도 됩니다. 아래애 @Before 어노테이션을 보면 속성에 바로 범위를 지정을 해놨는데요. 같은 방법으로 @Around에 속성을 지정해주어도 되고, Pointcut을 따로 지정해주는 메서드를 생성하셔도 됩니다.(내용은 없어도 돼요)


이전 포스팅에서 xml파일에서 설정했던 것과는 다르게 JAVA파일에서 어노테이션을 이용해서 설정을 해주었지만, xml파일에도 살짝 추가해야 될 것이 있습니다.


aopEx2/src/main/resources/applicationCtx.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
<?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-3.2.xsd">
 
<aop:aspectj-autoproxy/<!-- @Aspect어노테이션이 있는 클래스를 자동으로 찾아서 설정해줌 -->
<bean id="logAop" class="com.aopEx2.LogAop" />
 
<!-- AOP설정 -->
<!-- <aop:config>
    aspect id는 logger이고, logAop를 참조함
    <aop:aspect id="logger" ref="logAop">
        pointcut(핵심 기능)의 id는 publicM이고, com.aopEx패키지에 있는 모든 클래스에 공통 기능을 적용
        <aop:pointcut id="publicM" expression="within(com.aopEx.*)"/>
        loggerAop()라는 기능을 publicM라는 pointcut에 적용
        <aop:around pointcut-ref="publicM" method="loggerAop"/>
    </aop:aspect>
</aop:config> -->
 
 
<bean id="myCat" class="com.aopEx2.Cats">
    <property name="name" value="호랑이"/>
    <property name="age" value="1"/>
    <property name="color" value="yellow"/>
</bean>
 
</beans>
 
cs


<aop:aspectj-autoporxy/>를 명시해두면 @Aspect어노테이션이 있는 클래스를 찾아서 자동으로 aspect로 만들어줍니다. 그 아래는 bean객체를 생성했고, 이전 포스팅에서 사용한 XML방식의 AOP설정은 주석처리를 해놨습니다.


AOP설정은 끝났습니다. 메인클래스를 실행시키면 loggerAop()메서드와 @Before 어노테이션이 달려있는 beforeMethod가 실행이 되는데 beforeMethod()메서드는 핵심기능 이전에 한번만 실행이 되겠죠?



@Pointcut 어노에티션을 사용하지 않고, 범위를 바로 명시해줘도 가능합니다. 

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 com.aopEx2;
 
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
 
@Aspect //Aspect 역할을 할 클래스라고 명시해줌
public class LogAop {
    
    @Around("within(com.aopEx2.*)")
    public Object loggerAop(ProceedingJoinPoint joinpoint) throws Throwable{
        
        //공통 기능이 적용되는 메서드가 어떤 메서드인지 출력하기 위해 메서드명을 얻어옴
        String signatureStr = joinpoint.getSignature().toShortString();
        System.out.println(signatureStr + "시작"); //메서드 실행
        
        //공통기능
        System.out.println("핵심 기능 전에 실행 할 공통 기능입니다. "+System.currentTimeMillis());
        
        try {
            Object obj = joinpoint.proceed(); //핵심 기능 실행
            return obj;
        } finally {
            //공통기능
            System.out.println("핵심 기능 후에 실행 할 공통 기능입니다. "+System.currentTimeMillis());
            
            System.out.println(signatureStr + "끝");
        }
    }
 
}
 
cs



실행결과)




반응형

댓글

💲 추천 글