SpringAOP 实现机制介绍——JDKProxy

2024-08-21 15:32

本文主要是介绍SpringAOP 实现机制介绍——JDKProxy,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

List:

1.前言

2.AOP的实现方法

3.使用动态代理实现AOP

4.思考总结


……1.前言……

        

       AOP的应用场景有很多,权限、缓存、错误处理、日志记录、事务、性能优化等等。AOP的实现重点在于代理对象的生成,实现商业逻辑和通用服务的一种分离。这样做的好处是:核心关注点只关注业务流程,横切关注点只关注提供共性服务。实现了解耦,实现了共同逻辑的封装。


……2.AOP的实现方法……


2.1)静态AOP

     静态织入:写代码的时候,直接将切面写入。绑定好的,不灵活。


2.2)动态AOP

  • 动态代理:在运行中,通过类加载器(ClassLoader)加载目标类(被代理类)之后,为接口动态生成代理类(业务方法+服务方法),将切面(服务)织入到代理类(业务)中。
  • 动态字节码生成:在运行期,目标类加载后,动态构建字节码文件生成目标类的子类,将切面逻辑加入到子类中,使用Cglib来实现动态字节码技术
  • 自定义类加载器:在运行期,目标加载前,将切面逻辑加到目标字节码里
  • 字节码转换:在运行期,所有类加载器加载字节码前进行拦截

……3.使用JDKProxy实现AOP……


         动态代理的核心就是代理对象的生成,我们可以在运行期间通过NewProxyInstance方法 织入切面代码,并生成代理类。InvocationHandler是代理类的核心接口。通知类要实现这个接口,才能通过invoke方法来获取目标对象的方法。在运行期间,在当前类加载器的缓存中找代理类。如果没有,就通过上面的方法生成,加入jvm中。

   3.1)我们需要四种角色实现下面这个图。


  1. 被代理的类:Business
  2. 被代理的类的接口:IBusiness,IBusiness2
  3. 织入器:JDKProxy承担了织入器的角色。
  4. InvocationHandler的实现类:LogInvocationHandler 切面类

   3.2)实现的过程是:


  1. 织入器使用接口反射机制生成一个代理类。
  2. 在代理类中织入服务代码。
  3. 将代理类缓存到本地jvm被调用。

   3.3)实现代码:


1.IBusiness

public interface IBusiness {public boolean doSomeThing();
}


2.IBusiness2

public interface IBusiness2 {public void doSomeThing2() ;
}


3.Business

public class Business implements IBusiness, IBusiness2 {@Overridepublic boolean doSomeThing() {System.out.println("我是login服务的实现,业务逻辑1");return true;}@Overridepublic void doSomeThing2() {System.out.println("我是下订单的服务的实现,业务逻辑2");}
}


4.LogInvocationHandler

public class LogInvocationHandler  implements InvocationHandler {private Object target; //目标对象LogInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//执行原有逻辑Object rev = method.invoke(target, args);//执行织入的日志,你可以控制哪些方法执行切入逻辑//定义了切点(pointcut)doSomethingsif (method.getName().equals("doSomeThing")) {System.out.println("日志打印"+new Date()+" : 我是被织入的代码,after业务逻辑=====");}return rev;}
}


5.SussinessMain

public class BussinessMain {public static void main(String[] args) {//需要代理的接口,被代理类实现的多个接口都必须在这里定义Class[] proxyInterface = new Class[] { IBusiness.class, IBusiness2.class };//构建AOP的Advice,这里需要传入业务类的实例LogInvocationHandler handler = new LogInvocationHandler(new Business());//生成代理类的字节码加载器ClassLoader classLoader = BussinessMain.class.getClassLoader();//织入器,织入代码并生成代理类//classLoader字节码加载器
//        proxyInterface需要代理的接口(业务类的接口)
//        handler 切面,声明的是代理类IBusiness proxyBusiness = (IBusiness) Proxy.newProxyInstance(classLoader, proxyInterface, handler);//使用代理类的实例来调用方法。proxyBusiness.doSomeThing();
//        ((IBusiness) proxyBusiness).doSomeThing();}
}

console:





3.4)JDKProxy和Cglib的区别:


       如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP。可以强制使用Cglib。如果目标对象没有实现了接口,必须使用Cglib。在spring上下文配置中,<aop:aspectj-autoproxy proxy-target-class="true"/>
true表示让spring使用Cglib实现AOP,配置为false表示使用动态代理实现AOP,默认使用动态代理。


……4.思考总结……


         接口+类+切入逻辑 反射生成代理类,代理类封装了目标类,并拦截被通知的方法调用,再将调用转发给真正的目标 Bean。基于这个实现机制,再看AOP的代码就会清楚很多。



这篇关于SpringAOP 实现机制介绍——JDKProxy的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1093555

相关文章

MySQL中查找重复值的实现

《MySQL中查找重复值的实现》查找重复值是一项常见需求,比如在数据清理、数据分析、数据质量检查等场景下,我们常常需要找出表中某列或多列的重复值,具有一定的参考价值,感兴趣的可以了解一下... 目录技术背景实现步骤方法一:使用GROUP BY和HAVING子句方法二:仅返回重复值方法三:返回完整记录方法四:

IDEA中新建/切换Git分支的实现步骤

《IDEA中新建/切换Git分支的实现步骤》本文主要介绍了IDEA中新建/切换Git分支的实现步骤,通过菜单创建新分支并选择是否切换,创建后在Git详情或右键Checkout中切换分支,感兴趣的可以了... 前提:项目已被Git托管1、点击上方栏Git->NewBrancjsh...2、输入新的分支的

Spring事务传播机制最佳实践

《Spring事务传播机制最佳实践》Spring的事务传播机制为我们提供了优雅的解决方案,本文将带您深入理解这一机制,掌握不同场景下的最佳实践,感兴趣的朋友一起看看吧... 目录1. 什么是事务传播行为2. Spring支持的七种事务传播行为2.1 REQUIRED(默认)2.2 SUPPORTS2

Python实现对阿里云OSS对象存储的操作详解

《Python实现对阿里云OSS对象存储的操作详解》这篇文章主要为大家详细介绍了Python实现对阿里云OSS对象存储的操作相关知识,包括连接,上传,下载,列举等功能,感兴趣的小伙伴可以了解下... 目录一、直接使用代码二、详细使用1. 环境准备2. 初始化配置3. bucket配置创建4. 文件上传到os

关于集合与数组转换实现方法

《关于集合与数组转换实现方法》:本文主要介绍关于集合与数组转换实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、Arrays.asList()1.1、方法作用1.2、内部实现1.3、修改元素的影响1.4、注意事项2、list.toArray()2.1、方

使用Python实现可恢复式多线程下载器

《使用Python实现可恢复式多线程下载器》在数字时代,大文件下载已成为日常操作,本文将手把手教你用Python打造专业级下载器,实现断点续传,多线程加速,速度限制等功能,感兴趣的小伙伴可以了解下... 目录一、智能续传:从崩溃边缘抢救进度二、多线程加速:榨干网络带宽三、速度控制:做网络的好邻居四、终端交互

Python中win32包的安装及常见用途介绍

《Python中win32包的安装及常见用途介绍》在Windows环境下,PythonWin32模块通常随Python安装包一起安装,:本文主要介绍Python中win32包的安装及常见用途的相关... 目录前言主要组件安装方法常见用途1. 操作Windows注册表2. 操作Windows服务3. 窗口操作

MySQL中的锁机制详解之全局锁,表级锁,行级锁

《MySQL中的锁机制详解之全局锁,表级锁,行级锁》MySQL锁机制通过全局、表级、行级锁控制并发,保障数据一致性与隔离性,全局锁适用于全库备份,表级锁适合读多写少场景,行级锁(InnoDB)实现高并... 目录一、锁机制基础:从并发问题到锁分类1.1 并发访问的三大问题1.2 锁的核心作用1.3 锁粒度分

java实现docker镜像上传到harbor仓库的方式

《java实现docker镜像上传到harbor仓库的方式》:本文主要介绍java实现docker镜像上传到harbor仓库的方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录1. 前 言2. 编写工具类2.1 引入依赖包2.2 使用当前服务器的docker环境推送镜像2.2

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的