spring基础知识 (23):基于配置文件方式配置AOP

之前实现的AOP都是基于注解方式的,下面开始使用配置文件方式配置AOP:
目标对象 —— 计算器类

  • 接口:
package com.spring.aop.xml;

public interface Calculator {

    int add(int i,int j);
    int sub(int i,int j);
    int div(int i,int j);
}
  • 实现类:
package com.spring.aop.xml;


public class CalculatorImpl implements Calculator{

    @Override
    public int add(int i, int j) {
        int result = i + j;
        return result;
    }

    @Override
    public int sub(int i, int j) {
        int result = i - j;
        return result;
    }

    @Override
    public int div(int i, int j) {
        int result = i / j;
        return result;
    }

}
完全纯净,不包含而外功能代码,只包含自己功能的核心代码。
  • LoggingAspect —— 切面类:
package com.spring.aop.xml;

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

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

public class LoggingAspect {

    //前置通知
    public void beforeMethod(JoinPoint joinPoint){
        //注意,JoinPoint来自org.aspectj.lang.JoinPoint,小心导错包
        //执行方法名
        String methodName = joinPoint.getSignature().getName();
        //执行方法参数
        List<Object> args = Arrays.asList(joinPoint.getArgs());

        System.out.println("前置通知:method 【"+methodName+"】,args:"+args);
    }

    //后置通知
    public void afterMethod(JoinPoint joinPoint){
        //执行方法名
        String methodName = joinPoint.getSignature().getName();
        //执行方法参数
        List<Object> args = Arrays.asList(joinPoint.getArgs());

        System.out.println("后置通知:method 【"+methodName+"】,args:"+args);
    }

    //返回通知
    public void afterReturning(JoinPoint joinPoint){
        //执行方法名
        String methodName = joinPoint.getSignature().getName();
        //执行方法参数
        List<Object> args = Arrays.asList(joinPoint.getArgs());

        System.out.println("返回通知:method 【"+methodName+"】 ,args:"+args);
    }

    //异常通知
    public void afterThrowing(JoinPoint joinPoint,Exception ex){
        //执行方法名
        String methodName = joinPoint.getSignature().getName();
        //执行方法参数
        List<Object> args = Arrays.asList(joinPoint.getArgs());

        System.out.println("异常通知:method 【"+methodName+"】 ,args:"+args+",异常:"+ex);
    }

    //环绕通知
    public Object around(ProceedingJoinPoint pjd){
        Object result = null;
        //执行方法名
        String methodName = pjd.getSignature().getName();
        //执行方法参数
        List<Object> args = Arrays.asList(pjd.getArgs());

        try {
            //前置通知
            System.out.println("前置通知:method 【"+methodName+"】 begin:"+args);
            //执行方法
            result = pjd.proceed();

            System.out.println("返回通知:method 【"+methodName+"】 result:"+result);
        } catch (Throwable ex) {
            //异常通知
            System.out.println("异常通知:method 【"+methodName+"】 end:"+ ex);
        }
        //后置通知
        System.out.println("后置通知:method 【"+methodName+"】 end:"+args);
        return result;
    }

}

现在这个只是个普通的类,还没有配置为一个切面。

  • 配置文件:
<?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/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 配置bean -->
    <bean id="calculatorImpl" class="com.spring.aop.xml.CalculatorImpl"></bean>
    <!-- 配置切面bean -->
    <bean id="loggingAspect" class="com.spring.aop.xml.LoggingAspect"></bean>


    <aop:config>
        <!-- 配置切点表达式 -->
        <aop:pointcut expression="execution(* com.spring.aop.xml.CalculatorImpl.*(..))" id="pointcut"/>
        <!-- 配置切面及通知 -->
        <aop:aspect ref="loggingAspect" order="2">
            <!-- 前置通知 -->
            <aop:before method="beforeMethod" pointcut-ref="pointcut"/>
            <!-- 后置通知 -->
            <aop:after method="afterMethod" pointcut-ref="pointcut"/>
            <!-- 返回通知 -->
            <aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
            <!-- 异常通知 -->
            <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="ex"/>
            <!-- 环绕通知 
            <aop:around method="around" pointcut-ref="pointcut"/>   
            --> 
        </aop:aspect>

        <!-- 可以配置多个切面 
        <aop:aspect>
            ...
        </aop:aspect>
        -->
    </aop:config>

</beans>

配置AOP的一般步骤:

  1. 创建目标类的bean,将之交给spring容器管理。
  2. 创建切面类的bean,在后面的配置中会用到。
  3. 上面两个只是前提条件,下面开始正式配置AOP:
    1). 配置切点 —— 通知作用的目标方法
    2). 配置切面:先引用之前配置的切面bean,然后开始配置各种通知。

正常情况下, 基于注解的声明要优先于基于 XML 的声明. 通过 AspectJ 注解, 切面可以与 AspectJ 兼容, 而基于 XML的配置则是 Spring 专有的. 由于 AspectJ 得到越来越多的 AOP 框架支持, 所以以注解风格编写的切面将会有更多重用的机会.

猜你喜欢

转载自blog.csdn.net/abc997995674/article/details/80310932