基于配置xml的AOP入门实现步骤

1、先回忆一下基于注解的AOP步骤:

  1. 将目标类和切面类都加入到ioc容器中。@Component
  2. 告诉Spring哪个是切面类。@Aspect
  3. 在切面类中使用五个通知注解来配置切面中的这些通知方法都何时何地运行
  4. 开启基于注解的AOP功能

2、基于配置xml的AOP步骤:

//接口
package com.atguigu.inter;

public interface Calculator {

    public int add(int a, int b);
    public int sub(int a, int b);
    public int mul(int a, int b);
    public int div(int a, int b);

}
//实现类
package com.atguigu.impl;

import com.atguigu.inter.Calculator;
import org.springframework.stereotype.Service;

@Service
public class MyMathCalculator implements Calculator {

    @Override
    public int add(int a, int b) {
        return a+b;
    }

    @Override
    public int sub(int a, int b) {
        return a-b;
    }

    @Override
    public int mul(int a, int b) {
        return a*b;
    }

    @Override
    public int div(int a, int b) {
        return a/b;
    }
}
//第一个切面类
package com.atguigu.utils;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

public class ValidateAspect {

    public static void logStart(JoinPoint joinPoint){
        Object[] args = joinPoint.getArgs();//获取目标方法运行时使用的参数
        Signature signature = joinPoint.getSignature();//获取到方法签名
        String name = signature.getName();
        System.out.println("[validateAspect]["+ name +"]" + "方法开始执行了,用的参数列表是:["+ Arrays.asList(args) +"]");
    }

    public static void logReturn(JoinPoint joinPoint, Object result){
        Signature signature = joinPoint.getSignature();//获取到方法签名
        String name = signature.getName();
        System.out.println("[validateAspect]["+ name +"]" + "方法正常执行完成了,计算结果是:"+result);
    }

    public static void logException(JoinPoint joinPoint, Exception e){
        System.out.println("[validateAspect]["+ joinPoint.getSignature().getName() +"]"+ "出现了异常,异常原因是:"+"["+e+"]");
    }

    public static void logEnd(JoinPoint joinPoint){
        System.out.println("[validateAspect]["+ joinPoint.getSignature().getName() +"]" + "方法执行结束了。");
    }
}
//第二个切面类
package com.atguigu.utils;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;

public class LogUtils {

    public static void logStart(JoinPoint joinPoint){
        Object[] args = joinPoint.getArgs();//获取目标方法运行时使用的参数
        Signature signature = joinPoint.getSignature();//获取到方法签名
        String name = signature.getName();
        System.out.println("【LogUtils】["+ name +"]" + "方法开始执行了,用的参数列表是:["+ Arrays.asList(args) +"]");
    }

    public static void logReturn(JoinPoint joinPoint, Object result){
        Object[] args = joinPoint.getArgs();//获取目标方法运行时使用的参数
        Signature signature = joinPoint.getSignature();//获取到方法签名
        String name = signature.getName();
        System.out.println("【LogUtils】["+ name +"]" + "方法正常执行完成了,计算结果是:"+result);
    }

    public static void logException(JoinPoint joinPoint, Exception e){
        Object[] args = joinPoint.getArgs();//获取目标方法运行时使用的参数
        Signature signature = joinPoint.getSignature();//获取到方法签名
        String name = signature.getName();
        System.out.println("【LogUtils】["+ name +"]"+ "出现了异常,异常原因是:"+"["+e+"]");
    }

    public static void logEnd(JoinPoint joinPoint){
        Object[] args = joinPoint.getArgs();//获取目标方法运行时使用的参数
        Signature signature = joinPoint.getSignature();//获取到方法签名
        String name = signature.getName();
        System.out.println("【LogUtils】["+ name +"]" + "方法执行结束了。");
    }

    public Object myArround(ProceedingJoinPoint pjp) throws Throwable {
        //获取目标方法运行时使用的参数
        Object[] args = pjp.getArgs();
        String name = pjp.getSignature().getName();

        Object proceed = null;
        try {
            System.out.println("【LogUtils】[环绕前置通知],"+name+"方法开始");

            //利用反射调用目标方法,相当于method.invoke(obj, args);
            proceed = pjp.proceed(args);

            System.out.println("【LogUtils】[环绕返回通知],"+name+"方法返回,返回值:"+ proceed);
        } catch (Exception e) {
            System.out.println("【LogUtils】[环绕异常通知],异常信息:"+e);
        } finally {
            System.out.println("【LogUtils】[环绕后置通知],"+name+"方法最终结束。");
        }

        //反射调用后的返回值一定返回出去
        return proceed;
    }
}
  • 注意下面的配置文件,xsi:schemaLocation的配置信息,不能缺少。
<?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"
      xmlns:context="http://www.springframework.org/schema/context"
      xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">

   <!--基于配置xml的AOP步骤-->
   <bean id="myMathCalculator" class="com.atguigu.impl.MyMathCalculator"></bean>
   <bean id="logUtils" class="com.atguigu.utils.LogUtils"></bean>
   <bean id="validateAspect" class="com.atguigu.utils.ValidateAspect"></bean>

   <!--1、需要AOP名称空间-->
   <aop:config>
       <aop:pointcut id="globalPoint" expression="execution(* com.atguigu.impl.*.*(..))"/>
       <!--2、指定切面-->
       <aop:aspect ref="logUtils" order="1">
           <!--3、配置切入点表达式-->
           <aop:pointcut id="mypoint" expression="execution(* com.atguigu.impl.*.*(..))"/>
           <!--4、配置哪些方法是通知,有些通知还有返回注意-->
           <aop:before method="logStart" pointcut="execution(* com.atguigu.impl.*.*(..))"></aop:before>
           <aop:after-returning method="logReturn" pointcut-ref="mypoint" returning="result" ></aop:after-returning>
           <aop:after-throwing method="logException" pointcut-ref="mypoint" throwing="e"></aop:after-throwing>
           <aop:after method="logEnd" pointcut-ref="mypoint"></aop:after>
           <aop:around method="myArround" pointcut-ref="mypoint"></aop:around>
       </aop:aspect>

       <aop:aspect ref="validateAspect" order="2">
           <aop:before method="logStart" pointcut-ref="globalPoint"></aop:before>
           <aop:after-returning method="logReturn" pointcut-ref="globalPoint" returning="result"></aop:after-returning>
           <aop:after-throwing method="logException" pointcut-ref="globalPoint" throwing="e"></aop:after-throwing>
           <aop:after method="logEnd" pointcut-ref="globalPoint"></aop:after>
       </aop:aspect>
   </aop:config>

</beans>
  • 执行结果,可以看下每个切面方法的顺序。在LogUtils.java文件里面写了环绕通知,该类也是先于validateAspect先执行。
    在这里插入图片描述
  • 注意:这三个包也是必需的。
    在这里插入图片描述
发布了52 篇原创文章 · 获赞 1 · 访问量 2240

猜你喜欢

转载自blog.csdn.net/Shen_R/article/details/105204232