liguofeng29’s blog

個人勉強用ブログだっす。

Spring4 - AOP

SpringのAOP

Annotation (XML定義も可能ね)

  • @AspectJ
  • @Before
  • @After
  • @AfterReturing
  • @AfterThrowing
  • @Aroud
  • @Pointcut

必要なjar

  • aopalliance.jar
  • aspectjrt.jar
  • aspectjweaver.jar

コード

<?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:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context-4.0.xsd
  http://www.springframework.org/schema/aop
  http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
    <!-- bean検索 -->
    <context:component-scan base-package="app.aop"/>

    <!-- @AspectJ起動 -->
    <aop:aspectj-autoproxy/>

    <!-- xmlスキーマ使用しない場合 -->
    <!-- bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" -->
</beans>
package app.aop;

import java.util.Arrays;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Aspect
@Component
@Order(1) // 優先順位
public class FourAdviceTest {

    // pointcut定義
    @Pointcut("execution(* app.aop.*.*(..))")
    private void myPointCut(){}

    // pointcut実行前
    // @Before("execution(* app.aop.*.*(..))")
    @Before(value="myPointCut()")
    public void authority(JoinPoint jp) {
        System.out.println("Before advice.");
        System.out.println("目標オブジェクト" + jp.getTarget());
        System.out.println("目標メソッド : " + jp.getSignature().getName());
        System.out.println("目標メソッド引数 : " + Arrays.toString(jp.getArgs()));
    }

    // pointcut正常終了後
    @AfterReturning(pointcut = "execution(* app.aop.*.*(..))", returning = "ret")
    public void log(JoinPoint jp, String ret) {
        System.out.println("AfterReturning advice.");
        System.out.println("戻り値 : " + ret);
        System.out.println("目標オブジェクト" + jp.getTarget());
        System.out.println("目標メソッド : " + jp.getSignature().getName());
        System.out.println("目標メソッド引数 : " + Arrays.toString(jp.getArgs()));
    }

    // pointcut正常、異常終了後
    @After("execution(* app.aop.*.*(..))")
    public void release(JoinPoint jp) {
        System.out.println("After advice.");
        System.out.println("目標オブジェクト" + jp.getTarget());
        System.out.println("目標メソッド : " + jp.getSignature().getName());
        System.out.println("目標メソッド引数 : " + Arrays.toString(jp.getArgs()));
    }

    // pointcut前後、引数、戻り値修正可能
    // 強力な機能だな
    @Around("execution(* app.aop.*.*(..))")
    public Object processTx(ProceedingJoinPoint jp) throws java.lang.Throwable {
        System.out.println("Around advice.");

        Object[] args = jp.getArgs();
        if (args != null && args.length > 0
                && args[0].getClass() == String.class) {
            // 引数を修正する
            args[0] = "AAA" + args[0];
        }
        // pointcutを実行する
        Object ret = jp.proceed(args);
        System.out.println("pointcut実行完了");
        //
        if (ret != null && ret instanceof Integer)
            ret = (Integer) ret * (Integer) ret;
        return ret;
    }
}
package app.aop;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component("helloWorld")
@Scope("singleton")
public class HelloWorld{

    public String hello(String str1, String str2) {
        return str1 + str2;
    }
}
package app.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAOP {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("aop-beans.xml");

        HelloWorld h = (HelloWorld) context.getBean("helloWorld");
        h.hello("aaa", "bbb");
    }
}
Around advice.
Before advice.
目標オブジェクトapp.aop.HelloWorld@20d525
目標メソッド : hello
目標メソッド引数 : [AAAaaa, bbb]
pointcut実行完了
After advice.
目標オブジェクトapp.aop.HelloWorld@20d525
目標メソッド : hello
目標メソッド引数 : [AAAaaa, bbb]
AfterReturning advice.
戻り値 : AAAaaabbb
目標オブジェクトapp.aop.HelloWorld@20d525
目標メソッド : hello
目標メソッド引数 : [AAAaaa, bbb]