广告
返回顶部
首页 > 资讯 > 后端开发 > PHP编程 >Spring AOP使用接口方式实现
  • 805
分享到

Spring AOP使用接口方式实现

SpringAOP接口实现SpringAOP接口 2019-06-16 05:06:57 805人浏览 猪猪侠
摘要

目录一. 环境准备二、spring接口方式实现aop步骤1. 业务接口实现2. 业务类3. 通知类4. 自定义切## 点5.配置xml文件6. 方法入口三. 分析Spring 提供了很多的实现AOP的方式:Spring 接口方式,schem

目录
  • 一. 环境准备
  • 二、spring接口方式实现aop步骤
    • 1. 业务接口实现
    • 2. 业务类
    • 3. 通知类
    • 4. 自定义切## 点
    • 5.配置xml文件
    • 6. 方法入口
  • 三. 分析

    Spring 提供了很多的实现AOP的方式:Spring 接口方式,schema配置方式和注解.

    本文重点介绍Spring使用接口方式实现AOP. 研究使用接口方式实现AOP, 以了解为目的. 更好地理解spring使用动态代理实现AOP. 通常我们使用的更多的是使用注解的方式实现AOP

    下面来看看如何实现接口方式的AOP

    一. 环境准备

    要在项目中使用Spring AOP 则需要在项目中导入除了spring jar包之外, 还需要引入aspectjrt.jar,aspectjweaver.jar,aopalliance.jar ,spring-aop-3.2.0.M2.jar和cglib.jar

    二、Spring接口方式实现AOP步骤

    使用Spring aop接口方式实现aop, 可以通过自定义通知来供Spring AOP识别. 常见的自己定义通知有:前置通知, 后置通知, 返回通知, 异常通知, 环绕通知. 对应实现的接口是:

    1. 前置通知: MethodBeforeAdvice
    2. 后置通知: AfterAdvice
    3. 返回通知:AfterReturningAdvice
    4. 异常通知:ThrowsAdvice
    5. 环绕通知:MethodInterceptor

    实现步骤如下:

    1. 业务接口实现

    
    package com.lxl.www.aop.interfaceAop;
    
    
    public interface IBaseCalculate {
    
        int add(int numA, int numB);
    
        int sub(int numA, int numB);
    
        int div(int numA, int numB);
    
        int multi(int numA, int numB);
    
        int mod(int numA, int numB);
    
    }

    2. 业务类

    
    package com.lxl.www.aop.interfaceAop;//业务类,也是目标对象
    
    import com.lxl.www.aop.Calculate;
    
    import org.springframework.aop.framework.AopContext;
    import org.springframework.stereotype.Service;
    
    
    @Service
    public class BaseCalculate implements IBaseCalculate {
    
        @Override
        public int add(int numA, int numB) {
            System.out.println("执行目标方法: add");
            return numA + numB;
        }
    
        @Override
        public int sub(int numA, int numB) {
            System.out.println("执行目标方法: sub");
            return numA - numB;
        }
    
        @Override
        public int multi(int numA, int numB) {
            System.out.println("执行目标方法: multi");
            return numA * numB;
        }
    
        @Override
        public int div(int numA, int numB) {
            System.out.println("执行目标方法: div");
            return numA / numB;
        }
    
        @Override
        public int mod(int numA, int numB) {
            System.out.println("执行目标方法: mod");
    
            int retVal = ((Calculate) AopContext.currentProxy()).add(numA, numB);
            return retVal % numA;
        }
    }

    3. 通知类

    前置通知

    
    package com.lxl.www.aop.interfaceAop;
    
    import org.springframework.aop.MethodBeforeAdvice;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    
    
    @Component
    public class BaseBeforeAdvice implements MethodBeforeAdvice {
    
        
        @Override
        public void before(Method method, Object[] args, Object target) throws Throwable {
            System.out.println("===========进入beforeAdvice()============");
    
            System.out.println("目标对象:" + target);
            System.out.println("方法名: "+method);
    
            System.out.println("即将进入切入点方法");
        }
    }

    后置通知

    
    package com.lxl.www.aop.interfaceAop;
    
    import org.aspectj.lang.annotation.AfterReturning;
    import org.springframework.aop.AfterAdvice;
    import org.springframework.aop.AfterReturningAdvice;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    
    public class BaseAfterReturnAdvice implements AfterReturningAdvice {
    
        
        @Override
        public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
            System.out.println("==========进入afterReturning()=========== \n");
            System.out.println("切入点方法执行完成");
    
            System.out.println("后置通知--目标对象:" + target);
            System.out.println("后置通知--方法名: "+method);
            System.out.println("后置通知--方法入参: "+ args.toString());
            System.out.println("后置通知--方法返回值: "+ returnValue);
        }
    }

    异常通知

    
    package com.lxl.www.aop.interfaceAop;
    
    import org.springframework.aop.ThrowsAdvice;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    @Component
    public class BaseAfterThrowsAdvice implements ThrowsAdvice {
    
        
        public void afterThrowing(Method method, Object[] args, Object target, Throwable throwable) {
            System.out.println("出错啦");
        }
    }

    环绕通知

    
    package com.lxl.www.aop.interfaceAop;
    
    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    
    
    @Component
    public class BaseAroundAdvice implements MethodInterceptor {
    
        
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            System.out.println("===========around环绕通知方法 开始===========");
    
            // 调用目标方法之前执行的动作
            System.out.println("环绕通知--调用方法之前: 执行");
    
            // 调用方法的参数
            Object[] args = invocation.getArguments();
            // 调用的方法
            Method method = invocation.getMethod();
            // 获取目标对象
            Object target = invocation.getThis();
            System.out.println("输入参数:" + args[0] + ";" + method + ";" + target);
    
            // 执行完方法的返回值:调用proceed()方法,就会触发切入点方法执行
            Object returnValue = invocation.proceed();
    
            System.out.println("环绕通知--调用方法之后: 执行");
          
            System.out.println("输出参数:" + args[0] + ";" + method + ";" + target + ";" + returnValue);
    
            System.out.println("===========around环绕通知方法  结束===========");
    
            return returnValue;
        }
    }

    4. 自定义切## 点

    
    package com.lxl.www.aop.interfaceAop;
    
    
    import org.springframework.aop.support.NameMatchMethodPointcut;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    
    @Component
    public class Pointcut extends NameMatchMethodPointcut {
    
        private static final long serialVersionUID = 3990456017285944475L;
    
        @SuppressWarnings("rawtypes")
        @Override
        public boolean matches(Method method, Class targetClass) {
            // 设置单个方法匹配
            this.setMappedName("add");
            // 设置多个方法匹配
            String[] methods = { "add", "div" };
          
            //也可以用“ * ” 来做匹配符号
            // this.setMappedName("get*");
          
            this.setMappedNames(methods);
    
            return super.matches(method, targetClass);
        }
    }

    5.配置xml文件

    
    <?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:p="http://www.springframework.org/schema/p"
           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-3.0.xsd
    
              http://www.springframework.org/schema/context
              http://www.springframework.org/schema/context/spring-context-3.0.xsd
    
             http://www.springframework.org/schema/aop
              http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
    >
    
        <!-- ==============================aop配置================================ -->
        <!-- 声明一个业务类 -->
        <bean id="baseCalculate" class="com.lxl.www.aop.interfaceAop.BaseCalculate"/>
    
        <!-- 声明通知类 -->
        <bean id="baseBefore" class="com.lxl.www.aop.interfaceAop.BaseBeforeAdvice"/>
        <bean id="baseAfterReturn" class="com.lxl.www.aop.interfaceAop.BaseAfterReturnAdvice"/>
        <bean id="baseAfterThrows" class="com.lxl.www.aop.interfaceAop.BaseAfterThrowsAdvice"/>
        <bean id="baseAround" class="com.lxl.www.aop.interfaceAop.BaseAroundAdvice"/>
    
        <!-- 指定切点匹配类 -->
        <bean id="pointcut" class="com.lxl.www.aop.interfaceAop.Pointcut"/>
    
        <!-- 包装通知,指定切点 -->
        <bean id="matchBeforeAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
            <property name="pointcut">
                <ref bean="pointcut"/>
            </property>
            <property name="advice">
                <ref bean="baseBefore"/>
            </property>
        </bean>
    
        <!-- 使用ProxyFactoryBean 产生代理对象 -->
        <bean id="businessProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
            <!-- 代理对象所实现的接口 ,如果有接口可以这样设置 -->
            <property name="proxyInterfaces">
                <value>com.lxl.www.aop.interfaceAop.IBaseCalculate</value>
            </property>
    
            <!-- 设置目标对象 -->
            <property name="target">
                <ref bean="baseCalculate"/>
            </property>
            <!-- 代理对象所使用的拦截器 -->
            <property name="interceptorNames">
                <list>
                    <value>matchBeforeAdvisor</value>
                    <value>baseAfterReturn</value>
                    <value>baseAround</value>
                </list>
            </property>
        </bean>
    </beans>

    6. 方法入口

    
    package com.lxl.www.aop.interfaceAop;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class InterfaceMainClass{
    
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("aop/aop.xml");
            BaseCalculate calculate = (BaseCalculate) context.getBean("baseCalculate");
            calculate.add(1, 3);
        }
    }

    三. 分析

    各种类型通知的执行顺序: 前置方法会在切入点方法之前执行,后置会在切入点方法执行之后执行,环绕则会在切入点方法执行前执行同事方法结束也会执行对应的部分。主要是调用proceed()方法来执行切入点方法。来作为环绕通知前后方法的分水岭
    在xml 配置 businessProxy这个bean的时候,ProxyFactoryBean类中指定了,proxyInterfaces参数。这里把他配置了IBaseCalculate接口。因为在项目开发过程中,往往业务类都会有对应的接口,以方便利用ioc解耦。但Spring AOP却也能支持没有接口的代理。这就是为什么需要导入cglib.jar包了。看过spring的源码,知道在目标切入对象如果有实现接口,spring会默认使用jdk动态代理来实现代理类。如果没有接口,则会通过cglib来实现代理类。

    这个业务类现在有 前置通知,后置通知,环绕三个通知同时作用,可能以及更多的通知进行作用。那么这些通知的执行顺序是怎么样的?就这个例子而言,同时实现了三个通知。在例 子xml中,则显示执行before通知,然后执行around的前处理,执行切点方法,再执行return处理。最后执行around的后处理。经过测 试,知道spring 处理顺序是按照xml配置顺序依次处理通知,以队列的方式存放前通知,以压栈的方式存放后通知。所以是前通知依次执行,后通知到切入点执行完之后,从栈里 在后进先出的形式把后通知执行。

    在实现过程中发现通知执行对应目标对象的整个类中的方法,如何精确到某个方法,则需要定义一个切点匹配的方式:spring提供了方法名匹配或正则方式来匹配。然后通过DefaultPointcutAdvisor来包装通知,指定切点。

    使用接口方式配置起来,可见代码还是非常的厚重的,定义一个切面就要定义一个切面类,然而切面类中,就一个通知方法,着实没有必要。所以Spring提供了,依赖aspectj的schema配置和基于aspectj 注解方式。这两种方式非常简单方便使用,也是项目中普遍的使用方式。

    到此这篇关于Spring AOP使用接口方式实现的文章就介绍到这了,更多相关Spring AOP 接口实现内容请搜索编程界以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程界!

    --结束END--

    本文标题: Spring AOP使用接口方式实现

    本文链接: https://www.lsjlt.com/news/83.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    • Spring AOP使用接口方式实现
      目录一. 环境准备二、Spring接口方式实现AOP步骤1. 业务接口实现2. 业务类3. 通知类4. 自定义切## 点5.配置xml文件6. 方法入口三. 分析Spring 提供了很多的实现AOP的方式:Spring 接口方式,schem...
      99+
      2019-06-16
      Spring AOP 接口实现 Spring AOP 接口
    • 如何在SpringBoot中使用Spring-AOP实现接口鉴权
      目录面向切面编程AOP的底层原理实现AOP的相关术语相关注解以及切入点表达式实现接口鉴权1. 配置yml文件2. 读取账密配置3.编写接口鉴权方法4. 编写AOP5.编写接口测试面向...
      99+
      2022-11-13
    • Spring AOP实现的方式有哪些
      Spring AOP实现的方式有以下几种:1. 基于XML的配置:通过在Spring配置文件中使用元素来配置切面和通知。2. 基于注...
      99+
      2023-08-18
      Spring AOP
    • Spring AOP实现打印HTTP接口出入参日志
      目录前言思路1.编写一个HTTP接口2.编写一个AOP日志配置3.结果测试前言 最近在维护一个运营端的系统,和前端联调的过程中,经常需要排查一些交互上的问题,每次都得看前端代码的传参...
      99+
      2022-11-13
    • Spring AOP的几种实现方式总结
      Spring AOP的几种实现方式总结如下:1. 基于XML配置:在Spring配置文件中使用元素来定义切面和通知的配置,然后通过元...
      99+
      2023-08-17
      Spring AOP
    • 使用Spring特性实现接口多实现类的动态调用方式
      目录正好用到。mark一下背景问题的提出首先我们看一下这个方法的签名接下来看看我们遇到的问题是什么?实现代码如下验证关于SPI下面是JDBC驱动的接口下面是MySQL的JDBC驱动实...
      99+
      2022-11-13
    • Spring AOP 后置处理器使用方式
      目录1 前言2 BeanPostProcesser 后置处理器3 总结1 前言 在 Spring 的体系中,在前文中已经讲述了 IOC 容器以及 Bean 的理解,在本文基于之前文章...
      99+
      2022-11-13
    • Spring深入讲解实现AOP的三种方式
      [重点] 使用AOP织入 需要导入一个依赖包 <dependencies> <dependency> <gr...
      99+
      2022-11-13
    • Spring框架实现AOP的两种方式详解
      目录第一种AOP实现方式AfterLogLog配置文件实例调用定义接口第二种AOP实现方式第一种AOP实现方式 AfterLog package com.xxx.demo.servi...
      99+
      2022-11-13
    • springboot怎么利用aop实现接口异步
      小编给大家分享一下springboot怎么利用aop实现接口异步,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!一、前言在项目中发现有接口(excel导入数据)处理数据需要耗时比较长的时间,是因为数据量比较大,同时数据的校验...
      99+
      2023-06-22
    • spring boot拦截器如何使用spring AOP实现
      本篇文章为大家展示了spring boot拦截器如何使用spring AOP实现,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。在spring boot中,简单几步,使用spring AOP实现一个拦...
      99+
      2023-05-31
      springboot spring aop 拦截器
    • Spring学习通过AspectJ注解方式实现AOP操作
      目录Spring注解AspectJ操作AOP一、被增强类二、增强类三、进行通知的配置1. spring 配置文件中,开启扫描。2. 使用注解创建 User 和 UserProxy 对...
      99+
      2022-11-13
    • 使用SpringBoot + Redis 实现接口限流的方式
      目录配置限流注解定制 RedisTemplateLua 脚本注解解析接口测试全局异常处理Redis 除了做缓存,还能干很多很多事情:分布式锁、限流、处理请求接口幂等性。。。太多太多了...
      99+
      2022-11-13
    • Spring使用AspectJ的注解式实现AOP面向切面编程
      目录1、认识Spring AOP1.1 AOP的简介1.2 AOP中的概念 切入点(pointcut):2、认识AspectJ 2.1 AspectJ的简介2.2 Spring AO...
      99+
      2022-11-12
    • SpringBoot使用AOP记录接口操作日志的方法
      目录一、操作日志简介1.1、系统日志和操作日志的区别1.2、操作日志记录实现方式二、AOP面向切面编程2.1、AOP简介2.2、AOP作用2.3、AOP相关术语2.4、JointPo...
      99+
      2022-11-13
      SpringBoot AOP记录接口 SpringBoot AOP操作日志
    • 使用Swagger实现接口版本号管理方式
      目录Swagger实现接口版本号管理使用swagger测试接口Swagger实现接口版本号管理 前言:使用swagger暴露对外接口时原则是每个系统在不同的迭代版本仅仅需要暴露该迭代...
      99+
      2022-11-12
    • SpringBoot使用AOP实现统计全局接口访问次数详解
      目录AOP是什么AOP的作用和优势常见的动态代理技术AOP相关概念实现AOP是什么 AOP(Aspect Oriented Programming),也就是面向切面编程,是通过预编译...
      99+
      2022-11-13
    • SpringBoot如何使用AOP实现统计全局接口访问次数
      本篇内容主要讲解“SpringBoot如何使用AOP实现统计全局接口访问次数”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SpringBoot如何使用AOP实现统计全局接口访问次数”吧!AOP是...
      99+
      2023-07-02
    • Spring Security实现接口放通的方法详解
      目录1.SpringBoot版本2.实现思路3.实现过程3.1新建注解3.2新建请求枚举类3.3判断Controller方法上是否存在该注解3.4在SecurityConfig上进行...
      99+
      2022-11-13
    • 在Spring中AOP怎么使用注解来实现
      这期内容当中小编将会给大家带来有关在Spring中AOP怎么使用注解来实现,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。spring对AOP的实现提供了很好的支持。下面我们就使用Spring的注解来完成A...
      99+
      2023-05-31
      spring aop
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作