浅谈Spring切面编程AOP的实现,以及两种写法aspect和advisor

2023-11-06

在开发过程种,很多地方会用到Spring的AOP ,之前一致使用

<aop:aspect ref='eventMethodInterceptor'>
	<aop:before method='beforeMethod' pointcut-ref='prAspect'>
</aop:aspect>

,偶然间发现居然还有这种写法

<aop:advisor pointcut-ref='prAspect' advice-ref='eventMethodInterceptor' />

,顿时发现自己是多么无知,于是就赶快学习一下,记录一下,以供温故知新吧。

再次重复一下使用aop的目的,就是不改变源码的前提下,往一个方法的前后插入一个代码块

两者简单区别:
1、Adivisor是一种特殊的Aspect,Advisor代表spring中的Aspect
2、区别:advisor只持有一个Pointcut和一个advice,而aspect可以多个pointcut和多个advice
3、实现方式不同
< aop:aspect>定义切面时,只需要定义一般的bean就行,
< aop:advisor>中引用的通知时,通知必须实现MethodInterceptor接口

execution表达式规则:

*  只能匹配一级路径 
.. 可以匹配多级,可以是包路径,也可以匹配多个参数
+  只能放在类后面,表明本类及所有子类
//表示任意返回值,com.smallkey.dynamicProxy包及子包下的任意类,任意方法,任意参数
"execution(* com.smallkey.dynamicProxy..*.*(..))"

首先,看一下< aop:advisor>的实现方式:
我们定义一个目标类,代码如下:

//接口
public interface CustomerService {
    //保存
    public void save();
    //查询
    public int find();
}
// 实现类
@Service(value = "customerService")
public class CustomerServiceImpl implements CustomerService {
    @Override
    public void save() {
        //int a = 1/0; //测试异常通知
        System.out.println("客户保存了。。。。。");
    }

    @Override
    public int find() {
        System.out.println("客户查询数量了。。。。。");
        return 100;
    }
}

定义通知:

//定义通知(jdk的默认代理方式)
public class EventMethodInterceptor implements MethodInterceptor{
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("<aop:advisor advice-ref='' pointcut-ref=''>方式的通知");
        // 最后必须返回methodInvocation.proceed()执行目标方法
        return methodInvocation.proceed();
    }
}

//aop配置

<!--1、装配目标对象到ioc容器-->
    <bean id="customerService" class="com.smallkey.dynamicProxy.jdk.CustomerServiceImpl"/>
//把通知配置到Spring容器中
<bean id="EatHelper" class="com.ghs.aop.EatHelper"></bean>
<!--2、装配通知对象-->
<bean id="EventMethodInterceptor" class="com.smallkey.aopAdvice.EventMethodInterceptor"/>

<aop:config>
	<!--配置切点-->
    <aop:pointcut id="myPointcut" expression="execution(* com.smallkey.dynamicProxy..*.*(..))"/>
    <!--配置通知和切点,进行织入-->
    <aop:advisor advice-ref="EventMethodInterceptor" pointcut-ref="myPointcut"/>
</aop:config>

下面是< aop:aspect>的实现方式:
// 定义目标类

@Service(value = "customerService")
public class CustomerServiceImpl implements CustomerService {
    @Override
    public void save() {
        //int a = 1/0; //测试异常通知
        System.out.println("客户保存了。。。。。");
    }

    @Override
    public int find() {
        System.out.println("客户查询数量了。。。。。");
        return 100;
    }
}

//定义通知

@Component(value = "myAspectAdvice")
@Aspect
public class MyAspectAdvice {
    //参数1:连接点对象(方法的包装对象:方法,参数,目标对象)
    @Before("bean(*Service)")
    public void before(JoinPoint joinPoint) {
        System.out.println("方法名称" + joinPoint.getSignature().getName());
        System.out.println("目标对象" + joinPoint.getTarget().getClass().getName());
        System.out.println("代理对象" + joinPoint.getThis().getClass().getName());

        //判断是否是save方法
        if ("save".equals(joinPoint.getSignature().getName())) {
            System.out.println("前置通知~~~~");
        }
    }

    //参数1:连接点对象(方法的包装对象:方法,参数,目标对象)
    //参数2:目标方法执行后的返回值,类型是object,“参数名”随便,但也不能太随便,一会要配置
    @AfterReturning(value = "bean(*Service)",returning = "returnVal")
    public void afterReturning(JoinPoint joinPoint, Object returnVal) {
        System.out.println("后置通知:" + "小伙子您刚才调用的" + joinPoint.getSignature().getName() + "的返回值是" + returnVal);
    }

    //应用场景:日志、缓存、权限、性能监控、事务管理
    //环绕通知:在目标方法的执行前后均可增强
    //参数:ProceedingJointPoint可执行的连接点对象,特点是调用proceed()方法
    //可以随时随地执行目标对象的方法
    //必须抛出Throwable
    @Around(value = "bean(*Service)")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println(" 开启事务 ");
        Object resultObject = proceedingJoinPoint.proceed();
        System.out.println(" 关闭事务 ");
        return resultObject;
    }

    //当方法真正发生异常时才会增强方法
    //参数1:静态连接点(方法对象)
    //参数2:目标方法抛出的异常,参数名随便,但也不能太随便
    @AfterThrowing(value = "bean(*Service)",throwing = "throwable")
    public void afterThrowing(JoinPoint joinPoint, Throwable throwable) {
        System.out.println(
                joinPoint.getTarget().getClass().getName() + "类的"
                        + joinPoint.getSignature().getName()
                        + "方法发生异常,异常为" + throwable.getMessage()
        );
    }

    //不管目标方法是否发生异常,最终通知都会执行(类似于finally代码功能)
//应用场景:释放资源 (关闭文件、 关闭数据库连接、 网络连接、 释放内存对象
    @After(value = "bean(*Service)")
    public void after(JoinPoint joinPoint) {
        System.out.println("数据库的connection被释放了。。。。。,执行的方法是:"+
            joinPoint.getSignature().getName()
        );
    }
}

//aop配置

<!--1、装配目标对象到ioc容器-->
<bean id="customerService" class="com.smallkey.dynamicProxy.jdk.CustomerServiceImpl"/>
<bean id="cglibService" class="com.smallkey.dynamicProxy.cglib.CglibService"/>

<!--2、装配通知(增强)对象-->
<bean id="myAspectAdvice" class="com.smallkey.aopAdvice.MyAspectAdvice"/>

<!--3、配置切点和切面,进行织入-->
<aop:config>
    <!--配置切点-->
    <aop:pointcut id="myPointcut" expression="execution(* com.smallkey.dynamicProxy..*.*(..))"/>
    <!--配置切面-->
    <aop:aspect ref="myAspectAdvice">
        <!--<aop:before method="before" pointcut-ref="myPointcut"/>-->
        <!--<aop:after-returning method="afterReturning" returning="returnVal" pointcut-ref="myPointcut"/>-->
        <!--<aop:around method="around" pointcut-ref="myPointcut"/>-->
        <!--<aop:after-throwing method="afterThrowing" throwing="throwable" pointcut-ref="myPointcut"/>-->
        <aop:after method="after" pointcut-ref="myPointcut"/>
    </aop:aspect>
</aop:config>

其实除了xml方法,更多的使用注解的方法,让配置更简单
//通知对象、目标方法同上
//配置AOP

<!--只需要在applicationContent.xml中配置如下配置,在通知对象上配置@Aspect,在前置、环绕、后置方法上加@Before@Around@After,另外在切点方法返回后执行的方法加上@AfterReturning, 切点方法抛异常执行的方法加上@AfterThrowing-->
 <!--1、开启注解包扫描-->
 <context:component-scan base-package="com.smallkey"/>
 <!--2、开启AspectJ注解自动扫描-->
 <aop:aspectj-autoproxy/>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

浅谈Spring切面编程AOP的实现,以及两种写法aspect和advisor 的相关文章

随机推荐

  • 网络层协议-IP分组

    网络层Internet Protocol 在数据链路层提供的两个相邻端点之间的数据帧的传送功能上 进一步管理网络中的数据通信 将数据设法从源端经过若干个中间节点传送到目的端 从而向运输层提供最基本的端到端的数据传送服务 IP分组首部的格式功
  • Vue如何让页面加载时请求后台接口数据

  • NULL0路由的作用(概述)

    简单的来说 NULL0是属于路由器的逻辑接口 NULL0接口总是处于Up状态 但不转发任何报文 当NULL0接口接收到报文后 会把报文丢弃 不能在NULL0接口上配置IP地址 也不能在NULL0接口上封装任何链路层协议 NULL0主要用于防
  • Elasticsearch查询——Sort(查询排序)

    Sort 查询排序 测试索引 Elasticsearch针对普通数据 数组 嵌套对象 地理位置都提供了排序功能 为了测试其排序方式我们需要可以能够足够数据类型的索引 所以创建了下面一个索引以及其映射 PUT offline sales PU
  • AcWing 3708. 求矩阵的鞍点

    输入样例 3 4 1 2 3 4 1 2 3 4 1 2 3 4 输出样例 1 4 4 2 4 4 3 4 4 include
  • mysql安装(Linux中redhat版本,redhat密码破解)

    破解密码 1 先重启系统 开始界面点击鼠标入进电脑 按下e键 2 在界面中间输入rd break 输入Ctrl x执行 3 输入下面命令 修改命令 mount o 是字母o不是数字0 remount rw sysroot chroot sy
  • 【华为OD机试真题 python】等和子数组最小和【2022 Q4

    前言 华为OD笔试真题 python 专栏含华为OD机试真题 华为面试题 牛客网华为专栏真题 如果您正在准备华为的面试 或者华为od的机会 有任何想了解的可以私信我进行交流 我会尽可能的给一些建议 和帮您解答 PS 文中答案仅供参考 不能照
  • 操作系统实验—处理机调度算法的模拟

    操作系统实验 处理机调度算法的模拟 一 实验目的 二 实验内容 PCB进程控制块结构 设计要求 三 实验过程记录 1 算法的思路 2 主要数据结构 3 程序代码 运行效果 一 实验目的 熟悉处理器调度算法的工作原理 掌握调度算法的实现 进程
  • WEB网站常见受攻击方式及解决办法

    一个网站建立以后 如果不注意安全方面的问题 很容易被人攻击 下面就讨论一下几种漏洞情况和防止攻击的办法 一 跨站脚本攻击 XSS 跨站脚本攻击 XSS Cross site scripting 是最常见和基本的攻击WEB网站的方法 攻击者在
  • 大端小端问题总结及相关面试题

    昨天有一同学问了我一个关于大端小端的面试题 以前掌握的蛮好的现在突然之间想不起来了 回来翻了翻书 觉得现在有必要写一篇文章来记录一下这个知识点 大端小端是存储讲的是数据在内存中的存放顺序 大端存储格式就是自数据的高字节存放在低地址中 低字节
  • 数据库设计的 10 个最佳实践

    作者 Emily Williamson 译者 孙薇 责编 屠敏 出品 CSDN ID CSDNnews 以下为译文 数据库是应用及计算机的核心元素 负责存储运行软件应用所需的一切重要数据 为了保障应用正常运行 总有一个甚至多个数据库在默默运
  • make menuconfig 添加新选项

    如何在make menuconfig 界面添加新选项步骤 1 先在Linux内核源码目录下创建个新目录 哪个位置都行 一般添加新驱动时 都会在 drivers目录下创建 这里为了实验的方便就在 源码目录下创建了 mkdir hmq test
  • Visual Studio 2019(VS 2019)配置Qt开发环境(最新!)

    1 Qt下载与安装 1 Qt下载 Qt全版本下载网址 Index of archive qt 根据操作系统下载对应的安装包即可 我选择的是5 9 9的版本 2 Qt的安装 双击打开下载好的qt opensource windows x86
  • FRP代理及其在数据库安全上的实践

    1 代理 现如今的互联网世界里 代理服务已经十分常见 它通常作为一个第三方或者说中转站角色替代用户取得信息或者服务 根据代理对象的不同 代理服务可以分为正向代理和反向代理 1 1 正向代理 我们通常所说的代理一般都指的是正向代理 正向代理的
  • LlamaIndex 提供的索引

    LlamaIndex 以前称为 GPT Index 是一个开源项目 它在 LLM 和外部数据源 如 API PDF SQL 等 之间提供一个简单的接口进行交互 它提了供结构化和非结构化数据的索引 有助于抽象出数据源之间的差异 它可以存储提示
  • 严重漏洞已存在16年,数亿台打印机受影响

    聚焦源代码安全 网罗国内外最新资讯 编译 奇安信代码卫士 安全专家在惠普 Xerox 和三星使用的常用打印机驱动中找到一个严重漏洞 该漏洞编号为 CVE 201 3438 在2005年就存在于打印机驱动代码中 影响过去16年来出售的数亿台打
  • 火狐浏览器使用HttpRequester模拟发送http请求

    个人感觉网上的在线模拟http请求工具相比火狐的HttpRequester没那么实用方便 首先安装HttpRequester 打开菜单 附加组件 搜索框输入 HttpRequester 就会搜出来 然后点击安装 成功后在工具这里就会显示有H
  • Android数据的四种存储方式

    Android数据的四种存储方式 SharePreferences SQLite Contert Provider File 网络存储 作为一个完整的应用程序 数据存储的操作是必不可少的 Android系统提供了四种存储数据方式 分别为 S
  • Cache-Control浏览器缓存

    描述 同一个标签页 打开 A 站点 访问 config 接口 正常 打开 B 站点 访问 config 接口 正常 通过浏览器后退返回 A 站点 访问 config 接口 数据异常 config 返回了 B 站点的数据 测试站点数据 htt
  • 浅谈Spring切面编程AOP的实现,以及两种写法aspect和advisor

    在开发过程种 很多地方会用到Spring的AOP 之前一致使用