鲁春利的工作笔记,好记性不如烂笔头



基于XML配置方式声明切面


基于Schema的AOP从Spring2.0之后通过“aop”命名空间来定义切面、切入点及声明通知。

前面我们用到了标签,Spring在aop的命名空间里面还提供了其他的配置元素:

            定义一个AOP通知者
              后置通知
    返回通知
     异常通知
             环绕通知
             定义一个切面
             前置通知
             AOP顶级配置元素,其他元素都位于该元素之下
           定义一个切点,可重用

接口

package com.invicme.apps.aop;

/**
 * 
 * @author lucl
 * 
 * 数学计算接口类
 *
 */
public interface ArithmeticCalculate {
    public int add (int i, int j);
    public int div (int i, int j);
    public String validateNum (String level, int i);
}

实现类

package com.invicme.apps.aop.schema;

import org.apache.log4j.Logger;

import com.invicme.apps.aop.ArithmeticCalculate;

/**
 * 
 * @author lucl
 * 
 * 数学计算实现类
 *
 */
public class ArithmeticCalculateImpl implements ArithmeticCalculate {
    
    private static final Logger logger = Logger.getLogger(ArithmeticCalculateImpl.class);
    
    private int i = 0;
    private int j = 0;
    
    public ArithmeticCalculateImpl () {
        this(0, 0);
    }
    
    public ArithmeticCalculateImpl (int i, int j) {
        this.i = i;
        this.j = j;
    }
    
    @Override
    public int add(int i, int j) {
        logger.info("The method add was invoke with args [" + i + ", " + j + "]");
        int sum = i + j;
        logger.info("The method add ends with result [" + sum + "]");
        return sum;
    }

    @Override
    public int div(int i, int j) {
        logger.info("The method div was invoke with args [" + i + ", " + j + "]");
        int result = i / j;
        logger.info("The method div ends with result [" + result + "]");
        return result;
    }

    @Override
    public String validateNum(String level, int i) {
        logger.info("The method validateNum was invoke with args [" + level + ", " + i + "]");
        String result = this.getMsg(i);
        logger.info("The method validateNum ends with result [" + result + "]");
        return result;
    }

    private String getMsg (int i) {
        if (i > 0) {
            return "正数";
        }
        return "负数";
    }
}

切面POJO

package com.invicme.apps.aop.schema;

import java.util.Arrays;
import java.util.List;

import org.apache.log4j.Logger;
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.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

/**
 * 
 * @author lucl
 * 
 */
public class LogAdapter {
    private static final Logger logger = Logger.getLogger(LogAdapter.class);
     
    /**
     * Pointcut
     * 定义Pointcut,Pointcut的名称为poincutMethod(),此方法没有返回值和参数
     * 该方法就是一个标识,不进行调用
     */
    public void poincutMethod () {
        // ......
    }
    
    /**
     * 前置通知,在目标方法执行之前被调用(JoinPoint参数不是必须的,传入是为了获取目标对象的相关属性)
     */
    public void beforeAdvice (JoinPoint joinPoint) {
        // 目标对象
        Object target = joinPoint.getTarget();
        // 目标方法
        String methodName = joinPoint.getSignature().getName();
        // 方法参数
        List asList = Arrays.asList(joinPoint.getArgs());
        /**
         * target.getClass().getName() : 获取的是全路径名(包名+类名)
         * target.getClass().getSimpleName() : 获取类名
         */
        logger.info("[]" + target.getClass().getSimpleName() + "@" + methodName + " was invoke with args " + asList + ".");
    }
    
    /**
     * 后置通知(在目标方法执行之后被执行,无论该方法是否抛出异常)
     */
    public void afterAdvice (JoinPoint joinPoint) {
        // 目标对象
        Object target = joinPoint.getTarget();
        // 目标方法
        String methodName = joinPoint.getSignature().getName();
        logger.info("[]" + target.getClass().getSimpleName() + "@" + methodName + " ends.");
    }
    
    /**
     * 返回通知(在方法正常执行后执行,若出现异常不会被执行)
     * 返回通知可以获取到目标方法的返回值
     */
    public void afterReturningAdvice (JoinPoint joinPoint, Object result) {
        // 目标对象
        Object target = joinPoint.getTarget();
        // 目标方法
        String methodName = joinPoint.getSignature().getName();
        logger.info("[]" + target.getClass().getSimpleName() + "@" + methodName + " ends with result " + result + ".");
    }
    
    /**
     * 异常通知(当目标方法出现异常时会被执行,可以访问到异常,也可以通过指定异常类型,
     * 如Exception ex,也可以为NullPointerException ex则只有空指针异常才会被执行)
     */
    public void afterThrowingAdvice (JoinPoint joinPoint, Exception ex) {
        // 目标对象
        Object target = joinPoint.getTarget();
        // 目标方法
        String methodName = joinPoint.getSignature().getName();
        logger.info("[]" + target.getClass().getSimpleName() + "@" + methodName + " occurs exception : " + ex + ".");
    }
    
    /**
     * 环绕通知
     * 说明:
     *         环绕通知需要携带ProceedingJoinPoint类型的参数
     *         环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型参数可以决定是否执行目标方法
     *         环绕通知必须有返回值,且返回值为目标方法的返回值
     */
    public Object aroundAdvice (ProceedingJoinPoint joinPoint) {
        // 目标对象
        Object target = joinPoint.getTarget();
        // 目标方法
        String methodName = joinPoint.getSignature().getName();
        // 参数
        List asList = Arrays.asList(joinPoint.getArgs());
        // 
        Object result = null;
        // 执行目标方法
        try {
            // 前置通知
            result = joinPoint.proceed();
            // 返回通知
        } catch (Throwable e) {
            throw new RuntimeException(e);
            // 异常通知
            // 或者
            // 直接throw出去(否则程序会执行到最后的return result,而result为null,目标方法可能需要类型转换,当试图将null转化为特定类型时,出错)
        }
        // 后置通知
        logger.info("[]" + target.getClass().getSimpleName() + "@" + methodName + " was invoke with args " + asList + ", ends with " + result + " .");
        // 注意这里的result实际上是目标方法的返回值,如果出现问题返回值不匹配会出现错误
        return result;
    }
} 
  

Spring配置文件spring-context-aop-schema.xml




    
    
    
    
    
    
    
    
        
        
        
        
            
            
            
            
            
            
            
        
    

测试类

package com.test.apps.spring.aop;

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

import com.invicme.apps.aop.ArithmeticCalculate;

/**
 * 
 * @author lucl
 *
 */
public class TestSpringAopBySchema {
    @Test
    public void testSpringAopBySchema() {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring-context-aop-schema.xml");
        ArithmeticCalculate calculate = context.getBean("calculate", ArithmeticCalculate.class);
        calculate.add(1, 2);
        System.out.println("----------------------------------------------------------------");
        try {
            Thread.sleep(1 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        calculate.div(1, 0);
    }
}

运行结果:

Spring学习笔记AOP(三)_第1张图片


你可能感兴趣的:(xml,aop,JavaWeb)