Language/Java

Spring AOP AspectJ

아르비스 2014. 10. 8. 18:07

Spring AOP와 Aspectj를 사용하는 방법이다.


AspectJ로 사용할 수 있는 Annotation은 다음과 같다.


@Before – Run before the method execution

@After – Run after the method returned a result

@AfterReturning – Run after the method returned a result, intercept the returned result as well.

@AfterThrowing – Run after the method throws an exception

@Around – Run around the method execution, combine all three advices above.


AspectJ를 사용하기 위해서는 spectjrt.jar, aspectjweaver.jar and spring-aop.jar

를 추가해 주어야 한다.

(spring-aop.jar의 경우, spring-context.jar or spring-webmvc.jar 에 포함되어 있어서 없는 경우만 별도 추가한다.)

 Mavenj Pom.xml에 다음과 같이 추가 해 주어야 한다.

               <!-- AspectJ -->

<dependency>

<groupId>org.aspectj</groupId>

<artifactId>aspectjrt</artifactId>

<version>${org.aspectj.version}</version>

</dependency>

<dependency>

<groupId>org.aspectj</groupId>

<artifactId>aspectjweaver</artifactId>

<version>${aspectjweaver.version}</version>

</dependency>


              <!-- AOP -->

               <dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-aop</artifactId>

<version>${spring.version}</version>

       </dependency>


main 함수


public class App {

public static void main(String[] args) {

ApplicationContext appContext = new ClassPathXmlApplicationContext(

new String[] { "Spring-Context.xml" });

 

CustomerService cust = 

                                (CustomerService) appContext.getBean("customAspect");

 

System.out.println("*************************");

cust.printName();

System.out.println("*************************");

}

}




실행할 Service 구현

package com.sncap.service;


public class CustomerService {

private String name;

private String url;

 

public void setName(String name) {

this.name = name;

}

 

public void setUrl(String url) {

this.url = url;

}

 

public void printName() {

System.out.println("Customer name : " + this.name);

}

 

public void printURL() {

System.out.println("Customer website : " + this.url);

}

 

public void printThrowException() {

throw new IllegalArgumentException();

}

 }


Aspcet Code


package com.sncap.aspect; 


import org.aspectj.lang.JoinPoint;

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; 


@Aspect

public class LoggingAspect {

 

public void logBefore(JoinPoint joinPoint) {

  System.out.println("logBefore() is running!");

System.out.println("hijacked : " + joinPoint.getSignature().getName());

System.out.println("******");

}

       public void logAfter(JoinPoint joinPoint) {

  System.out.println("logAfter() is running!");

System.out.println("hijacked : " + joinPoint.getSignature().getName());

System.out.println("******");

  }

       

       public void logAfterReturning(JoinPoint joinPoint, Object result) {

         System.out.println("logAfterReturning() is running!");

       System.out.println("hijacked : " + joinPoint.getSignature().getName());

       System.out.println("Method returned value is : " + result);

       System.out.println("******");

       }


       public void logAfterThrowing(JoinPoint joinPoint, Throwable error) {

         System.out.println("logAfterThrowing() is running!");

       System.out.println("hijacked : " + joinPoint.getSignature().getName());

       System.out.println("Exception : " + error);

       System.out.println("******");

       }


       public void logAround(ProceedingJoinPoint joinPoint) throws Throwable {

         System.out.println("logAround() is running!");

       System.out.println("hijacked method : " + 

                                          joinPoint.getSignature().getName());

       System.out.println("hijacked arguments : " + 

                                          Arrays.toString(joinPoint.getArgs()));

         System.out.println("Around before is running!");

       joinPoint.proceed(); //continue on the intercepted method

       System.out.println("Around after is running!");

         System.out.println("******");

        }

}


위와 같은 Aspect code를 생성한 후 xml을 통해서 load한다.

method위에 annotation 형태로도 가능하다.

ex)

@Aspect

public class LoggingAspect {

    @Around("execution(* com.sncap.aspect.LoggingAspect.logAround(..))")

   public void logAround(ProceedingJoinPoint joinPoint) throws Throwable {

    }


하지만, 변경시 마다 code를 수정해야 하는 불편함 때문에, xml에 정의하는 것을 (본좌는)선호한다.


[Encable AspectJ]

(spring-context.xml)


<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-3.0.xsd 

http://www.springframework.org/schema/aop 

http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">

 

<bean id="customAspect"      

                           class="com.sncap.aspec.LoggingAspect " />


<aop:aspectj-autoproxy />

 

<!-- Aspect -->

        <aop:config>

             <aop:aspect id="before" ref="customAspect">

                <aop:pointCut id="pointCutBefore" 

                      expression="expression(public * com.sncap..*Service.*(..))" />

                

                <aop:before method="logBefore" pointcut-ref="before" />

                <aop:after method="logAfter" pointcut-ref="before" />

                <aop:afterr-returning 

                                 method="logAfterReturning" pointcut-ref="before" />

                <aop:after-throwing 

                                 method="logAfterThrowing" pointcut-ref="before" />

                <aop:around method="logAround" pointcut-ref="before" />

             </aop:aspect>

      </aop:config>

</beans>


sncap 폴더 하위의 모든 package 중 *Service class의 모든 method에 대해서 Aspect를 수행한다.


실행시는 Asjpect code 부분의 호출 없이 아래와 같이 Service를 실행하면 같이 수행된다.

예는 around만 수행함.


Run it

   CustomerService service = 

              (CustomerService) appContext.getBean("customAspect");

     service.logAround("sncap");



Output

*************************

logAround() is running!

hijacked method : logAround

hijacked arguments : sncap

Around before is running

sncap

Around after is running!

*************************