AOP(Aspect Orient Programming),称之为面向切面编程。Spring AOP是使用了动态代理实现的,所谓的动态代理就是说Spring不会去修改字节码,而是在内存中临时为方法生成一个代理对象,这个代理对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。

Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler接口和Proxy类。

如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,它可以在运行期动态扩展Java类与实现Java接口,通俗说CGLIB可以在运行时动态生成字节码。注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。

1、JDK动态代理

JDK动态代理要求被代理的类必须至少实现一个接口,如果目标类没有实现接口,则不能使用JDK动态代理,只能使用CGLIB动态代理。JDK动态代理会创建一个与目标类实现相同接口的代理类,然后创建该类的对象,在相应的切点做增强处理,然后调用目标对象的同名方法。

下面实现一个简单的JDK动态代理:

先定义一个接口:

public interface Person {public abstract void say();}

给定一个该接口的实现类:

public class Chinese implements Person{public void say() {System.out.println("你好!");        }}

下面是实现动态代理的核心类,该类实现了InvocationHandler接口:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class MyInvocationHandler implements InvocationHandler{//被代理的对象private Object target;public Object getProxy(Object target){this.target=target;//通过Proxy类创建代理对象,该对象的代理类实现了getInterfaces()指定的一系列接口return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);}public Object invoke(Object proxy, Method method, Object[] args) throws Exception{//织入前置增强处理System.out.println("前置处理。。。");//采用反射方式调用目标对象的方法Object result=method.invoke(target, args);//织入后置增强处理System.out.println("后置处理。。。");//方法的返回值return result;}}

下面是测试类:

public class Test {public static void main(String[] args){MyInvocationHandler myInvocationHandler=new MyInvocationHandler();Person chinese=(Person) myInvocationHandler.getProxy(new Chinese());chinese.say();}}

运行结果:

前置处理。。。
你好!
后置处理。。。

可以看到,目标类Chinese被进行了增强处理。

JDK动态代理的核心是InvocationHandler接口和Proxy类,下面讲解一下InvocationHandler接口的invoke()方法和Proxy类的newProxyInstance()方法。

InvocationHandler接口:
public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
参数说明:
Object proxy:指被代理的对象。
Method method:要调用的方法
Object[] args:方法调用时所需要的参数 

Proxy类提供了用于创建动态代理类和代理对象的静态方法,可以通过此类为一个或多个接口动态地生成实现类,它也是所有动态代理类的父类,此类提供了如下的操作方法:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,
InvocationHandler h) throws IllegalArgumentException
参数说明:
ClassLoader loader:生成动态代理类的类加载器
Class<?>[] interfaces:目标类(被代理类)实现的所有接口
InvocationHandler h:得到InvocationHandler接口的子类实例 

2、CGLIB动态代理

CGLIB是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

下面定义一个类,该类并没有实现任何接口:

public class Chinese {public void say(){System.out.println("你好!");}}

下面是实现CGLIB动态代理的核心类,该类实现了MethodInterceptor接口:

import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;public class DynamicProxy implements MethodInterceptor{//被代理的对象private Object target;public Object getProxy(Object target){this.target=target;//创建增强器,用来动态创建代理类Enhancer enhancer=new Enhancer();//设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦截enhancer.setCallback(this);//为要生成的代理类指定父类enhancer.setSuperclass(target.getClass());//创建代理类的对象return enhancer.create();}public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {//织入增强处理System.out.println("前置处理。。。");//调用相应方法//等价于Object result=method.invoke(target, args);//等价于Object result=methodProxy.invokeSuper(object, args);      Object result=methodProxy.invoke(target, args);//织入增强处理System.out.println("后置处理。。。");return result;}}

intercept()方法参数说明:

Object object:生成的代理类的实例

Method method:被代理类的方法

Object[] args:方法的参数

MethodProxy methodProxy:代理类的方法

下面是测试类:

public class Test {public static void main(String[] args) {DynamicProxy proxy=new DynamicProxy();Chinese chinese=(Chinese)proxy.getProxy(new Chinese());chinese.say();}}

运行结果如下:

前置处理。。。
你好!
后置处理。。。

可以看到Chinese类的say()方法被进行了增强处理。

Spring AOP的应用场景:

  • 访问控制
  • 日志记录
  • 事务管理
  • 性能监测
  • 对象池管理
  • 缓存

Spring AOP实现原理相关推荐

  1. Spring AOP实现原理,从代理说起

    前言 为了理解Spring AOP,我们先来了解一下Java的代理模式 什么是代理? 举个例子来说明代理的作用: 假设我们想邀请一位明星,那么并不是直接联系明星,而是联系明星的经纪人,来达到同样的目的 ...

  2. spring注解驱动开发-6 Spring AOP实现原理

    Spring AOP实现原理 前言 1.@EnableAspectJAutoProxy注解原理 2.AnnotationAwareAspectJAutoProxyCreator 分析 1.分析前工作, ...

  3. ppst——技术视频spring AOP 的原理讲解和简单实现

    ppst 技术视频--spring AOP 的原理讲解和简单实现:请访问ppst 技术视频分享平台 , www.ppst.cc,上面有最新的技术视频,推荐大家把博客录制成视频吧,可以获取收益哦 1.s ...

  4. 灵魂画手图解Spring AOP实现原理!

    本篇旨在让读者对Spring AOP实现原理有一个宏观上的认识,因此会丢失一些细节,具体实现参考:老实人Spring源码目录 阅读本篇文章前,希望读者对Spring Ioc以及Spring AOP的使 ...

  5. 探秘Spring AOP (六) Spring AOP 实现原理 1

    2019独角兽企业重金招聘Python工程师标准>>> 探秘Spring AOP 一.织入的时机原理概述 1.编译期(AspectJ) 2.类加载时(AspectJ 5+) 3.运行 ...

  6. Spring AOP 实现原理与 CGLIB 应用--转

    AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理.安全检查.缓存.对象池管理等.AOP 实现的关键就在于 ...

  7. Spring AOP 实现原理与 CGLIB 应用

    WeiboGoogle+用电子邮件发送本页面 10 AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理.安 ...

  8. spring aop实现原理_Spring 异步实现原理与实战分享

    最近因为全链路压测项目需要对用户自定义线程池 Bean 进行适配工作,我们知道全链路压测的核心思想是对流量压测进行标记,因此我们需要给压测的流量请求进行打标,并在链路中进行传递,那么问题来了,如果项目 ...

  9. Spring AOP:原理、 通知、连接点、切点、切面、表达式

    0:Spring AOP 原理 简单说说 AOP 的设计: 每个 Bean 都会被 JDK 或者 Cglib 代理.取决于是否有接口. 每个 Bean 会有多个"方法拦截器".注意 ...

  10. 常见面试题 | Spring AOP 实现原理

    实现AOP的技术,主要分为两大类: 一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执 行:二是采用静态织入的方式,引入特定的语法创建"方面",从而 ...

最新文章

  1. Windows客户端C/C++编程规范“建议”——表达式和运算
  2. 【linux】NXP MFGTools工具配置文件详解
  3. SAP S4HANA如何取到采购订单ITEM里的'条件'选项卡里的条件类型值?
  4. linux安装python虚拟环境_linux环境下安装python虚拟环境及注意事项
  5. Flex+J2EE获取FlexSession的方法
  6. 剑指offer---包含min函数的栈
  7. Ubuntu中安装python3
  8. js实战代码系列—周杰伦给你报时间+网页页签制作模板+jQuery初体验
  9. [转] ASP.NET中使用javascript
  10. 【读书笔记】 —— 公平与正义
  11. SSM框架面试题整理
  12. 2020微博热点数据简析
  13. PAT1003 我要通过! (20 分)(C语言)
  14. Arch Linux KDE Plasma + Windows 11 双系统安装指南
  15. 石子合并——最经典的dp问题
  16. json spirit_Spirit App:Web实时轻松动画
  17. sporadic偶发实时任务多核分区动态优先级EDF(或者DM)调度(以及可调度性分析)经典算法详解
  18. vue-quill-editor富文本编辑器自定义上传图片功能
  19. 百度云图片识别(ImageRecognition) 针对 各种图片识别的例子
  20. 织梦DEDE三级栏目导航实现 亲测有效

热门文章

  1. javascript页面刷新的几种方法
  2. 20多个好用的 Vue 组件库
  3. 【解决方法】Socket服务端退出之后端口依旧被占用
  4. matlab二重积分计算程序,MATLAB在二重积分计算中的应用
  5. git与svn的区别
  6. 导纳矩阵 matlab,matlab实现导纳矩阵
  7. 手机无法服务器获取信息,荒野行动获取服务器信息一直不动怎么办 获取服务器信息为0解决方法...
  8. MarkDown桌面版使用下载+安装+使用教程(包括全套的使用语法,欢迎大家查看)
  9. 批量图片处理:如何给多个图片都加上连续的序号?
  10. 毕业论文答辩PPT模板