当前位置: 首页 > article >正文

Java进阶 - AOP

概念

        AOP(Aspect-Oriented Programming),面向切面编程。旨在不改变程序现有代码的前提下,可以设置某方法运行前或运行后新增额外代码的操作,减少对代码的入侵。

        AOP并不是Spring框架独有的,而是从AspectJ框架中借鉴而来。包括过滤器、拦截器都是一种AOP的思想。主要应用于:日志收集、事务管理、安全检查、缓存、对象池管理等。

AOP基本概念:

  1. 切面(Aspect):是一个可以加入额外代码运行的特定位置,一般指方法之间的调用,可以在不修改原代码的情况下,添加新的代码,对现有代码进行升级维护和管理。
  2. 织入(Weaving):选定一个切面,利用动态代理技术,为原有的方法的持有者生成动态对象,然后将它和切面关联,在运行原有方法时,就会按织入之后的流程运行了。
  3. 目标对象(Target):需要被加强的业务对象
  4. 代理类(Proxy):一个类被AOP织入通知后,就产生了一个代理类。
  5. 切点(PointCut):每个程序的连接点有多个,如何定位到某个感兴趣的连接点,就需要通过切点来定位。
  6. 连接点(Joinpoint):程序执行的某个特定位置,如某个方法调用前,调用后,方法抛出异常后,这些代码中的特定点称为连接点。连接点表示具体要拦截的方法,切点是定义一个范围,而连接点是具体到某个方法。
  7. 通知(Advice):原意为增强,是织入到目标类连接点上的一段程序代码。

AspectJ框架

        AspectJ是一个面向切面的框架,是目前最好用,最方便的AOP框架,和Spring中的aop可以集成在一起使用,通过Aspectj提供的一些功能实现aop代理变得非常方便。

AspectJ使用步骤:

  1. 创建一个类,使用@Aspect标注
  2. @Aspect标注的类中,通过@Pointcut定义切入点
  3. @Aspect标注的类中,通过AspectJ提供的一些通知相关的注解定义通知
  4. 使用AspectJProxyFactory结合@Ascpect标注的类,来生成代理对象

 

Spring AOP

        SpringAOP作为AOP的一种实现,基于动态代理的实现AOP,意味着实现目标对象的切面会创建一个代理类,代理类的实现有两种不同的模式,分为两种不同的代理。

        Spring AOP利用的是运行时织入,在SpringAOP中连接点是方法的执行。在实际生产中,我们用得最多的还是 Spring AOP,其底层采用的是JDK/CGLIB动态代理。

引入AspectJ依赖

另外,在SpringAOP的实现中,借用了AspectJ的一些功能,比如@Aspcet、@Before、@PonitCut这些注解,都是AspectJ中的注解。在使用SpringAOP的时候需要引入AspectJ的依赖。

@Aspect注解方式

@Aspect注解方式,它的概念都是来自于 AspectJ,但是功能的实现是纯 Spring AOP 自己实现的,主要有两大核心:

  1. 定义[切入点]:使用 @Pointcut 切点表达式。
  2. 定义[切入时机] 和 [增强处理逻辑]:五种通知Advice注解 对[切入点]执行增强处理, 包括:@Before、@After、@AfterRunning、@AfterThrowing、@Around

 

@Pointcut

         @Pointcut用来标注在方法上来定义切入点。格式:@ 注解(value=“表达标签 (表达式格式)”),如:

       ​​​​

表达式标签(10种)

  • execution:用于匹配方法执行的连接点
  • within:用于匹配指定类型内的方法执行
  • this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配
  • target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配
  • args:用于匹配当前执行的方法传入的参数为指定类型的执行方法
  • @within:用于匹配所以持有指定注解类型内的方法
  • @target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解
  • @args:用于匹配当前执行的方法传入的参数持有指定注解的执行
  • @annotation:用于匹配当前执行方法持有指定注解的方法

        

  • bean:Spring AOP扩展的,AspectJ没有对于指示符,用于匹配特定名称的Bean对象的执行方法

@Before 前置通知

前置通知在被切的方法执行之前执行,比如获取连接对象等。

这里有个非常重要参数JoinPoint:连接点 。因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法. 里面有三个常用的方法,基于这3个方法,可以轻松打印:被切的类名、方法名、方法参数值、方法参数类型等。

  • getSignature()获取签名

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();

        通过signature可以获取名称 getName() 和 参数类型 getParameterTypes()

  • getTarget()获取目标类

Class<?> clazz = joinPoint.getTarget().getClass(); 如果被切的类是被别的切面切过的类,可以使用AopUtils.getTargetClass获取一个数组,再从数组中找你期望的类。

  • getArgs()获取入参值

        Object[] args = joinPoint.getArgs()

@After 后置通知

后置通知在被切的方法执行之后执行,无论被切方法是否异常都会执行,比如关闭连接对象等。

@AfterRunning 返回通知

返回通知在被切的方法return后执行,带有返回值,如果被切方法异常则不会执行。这里多了一个参数Object result,注解上也多了一个参数:returning

@AfterThrowing 异常通知

异常通知只在被切方法异常时执行,否则不执行,比如回滚事务。

这里多了一个参数Exception e,表示捕获所有异常,也可以设置为具体某一个异常,例如NullPointerException、RpcException等等。注解上也多了一个参数:throwing

@Aroud 环绕通知

环绕通知方法可以包含上面四种通知方法,是最全面最灵活的通知方法。可以决定目标方法是否执行,什么时候执行,执行时是否需要替换方法参数,执行完毕是否需要替换返回值。

这里的参数类型和其它通知方法不同,从JoinPoint变为ProceedingJoinPoint

AopContext

        参考资料:AopContext.currentProxy() - 简书

        Spring AOP模式是不暴露出来的,也就是默认AopContext.currentProxy()方法默认返回的都是null,需要配置Aop代理对象暴露,需要通过 @EnableAspectJAutoProxy(exposeProxy = true) 注解开启。

 


http://www.kler.cn/a/395810.html

相关文章:

  • 安全,服务器证书和SSL连接
  • gitHub常用操作
  • apk反编译修改教程系列-----apk应用反编译中AndroidManifest.xml详细代码释义解析 包含各种权限 代码含义【二】
  • 民事诉讼中,火灾事故认定书并非不可推翻,其证明力弱于鉴定意见
  • 使用python-Spark使用的场景案例具体代码分析
  • JSON.stringify的应用说明
  • 无人机:科技改变生活的神奇力量
  • 商城小程序(源码+文档+部署+讲解)
  • java Stack详解
  • Ken和Bwk趣说UNIX
  • YOLOv11改进,YOLOv11添加GnConv递归门控卷积,二次创新C3k2结构
  • 【数据结构】什么是链栈?
  • 李沐《动手学深度学习》kaggle树叶分类(ResNet18无预训练)python代码实现
  • 头歌网络安全(11.12)
  • windows C#-查询表达式基础(二)
  • UNI-APP小程序答题功能开发(左右滑动,判断,填空,问答,答题卡,纠错,做题倒计时等)
  • 深度强化学习方法--三维路径规划算法设计与实现(RRT+AOC+APF)
  • 学习yum工具,进行安装软件
  • 操作系统——同步
  • 单体架构 IM 系统之长轮询方案设计
  • 【操作系统】每日 3 题(二十四)
  • ARM-Linux嵌入式开发环境搭建
  • xrandr源码分析
  • finalshell的使用
  • Java集合框架高频面试问题精粹(下篇)
  • NodeJS 百度智能云文本转语音(实测)