Spring 的 AOP 概述和底层实现
Spring 的 AOP 概述和底层实现
1. 什么是 AOP
- AOP (Aspect Oriented Programing),即面向切面编程
- AOP 采取横向抽取机制,取代了传统纵向继承体系重复性代码(性能监视、事务管理、安全检查、缓存)
- Spring AOP 使用纯 Java 实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码
简单的来说就是:
生成和目标类一样的类或者继承目标类,生成子类,我们都把该类叫做代理类,然后通过代理方式在代理类中添加方法,以达到对目标类中的方法进行增强的目的。
2. AOP 相关术语
Joinpoint(连接点):
所谓连接点是指那些可以被拦截的点。在 spring 中,这些点指的是方法,因为 spring 只支持方法类型的连接点。
比如增删改查这些方法都可以增强,这些方法称为是连接点。
Pointcut(切入点):
指的是真正被拦截的点。
比如我们只想对类中的 save()
方法进行增强(做权限校验),save
方法称为是切入点。
Advice(通知/增强):
指拦截到 Joinpoint 之后所要做的事。
通知分为前置通知(方法执行之前)、后置通知(方法执行之后)、异常通知、最终通知、环绕通知(切面要完成的功能)
比如对 save
方法要进行权限校验,权限校验的方法称为是通知。
Introduction(引介):
引介是一种特殊的通知在不修改类代码的前提下,Introduction 可以在运行期为类动态地添加一些方法或 Field。
Target(目标对象):
代理(被增强)的目标对象。
Weaving(织入):
是指把增强(Advice)应用到目标对象(Target)来创建新的代理对象的过程。
比如将权限校验应用到 UserDaoImpl
的 save
方法的这个过程。
Proxy(代理):
一个类被 AOP 织入增强后,就产生一个结果代理类。
Aspect(切面):
是切入点和通知(引介)的结合。
3. Spring 的底层实现原理
两种实现:
- JDK 动态代理
- CGLIB生成代理
JDK 动态代理:
public class MyJdkProxy implements InvocationHandler{
private UserDao userDao;
public MyJdkProxy(UserDao userDao) {
this.userDao = userDao;
}
public Object createProxy() {
// 获得目标类
Object proxy = Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), this);
return proxy;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 对 save 进行增强
if ("save".equals(method.getName())) {
System.out.println("权限校验...");
// args 参数化,UserDao中方法列表
return method.invoke(userDao, args);
}
// invoke 调用 UserDao 中的方法
return method.invoke(userDao, args);
}
}
其中:
Proxy.newProxyInstance();
方法需要传入三个参数:类的加载器,类实现的接口,InvocationHandler
的接口。三个参数:
userDao.getClass().getClassLoader()
userDao.getClass().getInterfaces()
- 通过匿名内部类或使用
implements InvocationHandler
接口,再通过 this 实例化
然后在测试类中 new 代理类,这样我们在测试类中调用实现类中的方法就相当于变成了调用动态代理类中的 invoke 方法。
注意:
JDK 动态代理是对实现接口类实行代理,建立一个实现目标类中方法的代理类。(面向接口)
CGLIB生成代理:
public class MyCglibProxy implements MethodInterceptor{
private ProductDao productDao;
public MyCglibProxy(ProductDao productDao) {
this.productDao = productDao;
}
public Object createProxy() {
//1. 创建核心类
Enhancer enhancer = new Enhancer();
//2. 设置父类
enhancer.setSuperclass(productDao.getClass());
//3. 设置回调
enhancer.setCallback(this);
//4. 生成代理(子类)
Object proxy = enhancer.create();
return proxy;
}
//回调函数中实例化 MethodInterceptor 接口方法(intercept, 类似于 invoke 方法),通过 this
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if ("save".equals(method.getName())) {
System.out.println("权限校验=========");
}
// invokeSuper 调用父类 ProductDao 方法
return methodProxy.invokeSuper(proxy, args);
}
}
- 对于不使用接口的业务类,无法使用 JDK 动态代理
- CGLIB 采用非常底层字节码技术,可以为一个类创建子类,解决无接口代理问题
注意:
CGLIB 实现和 JDK 动态代理不同,是生成一个类来继承目标类。
4. 代理知识总结
- 程序中应优先对接口创建代理,便于程序解耦维护
- 标记为 final 的方法,不能被代理,因为无法进行覆盖
- JDK 动态代理,是针对接口生成子类,接口中方法不能使用 final 修饰
- CGLIB 是针对目标类生成子类,因此类或方法不能使用 final
- Spring 只支持方法连接点,不提供属性连接
附:
spring 核心包有四个:
- spring-context
- spring-beans
- spring-expression
- spring-core
Spring 的 AOP 概述和底层实现的更多相关文章
- spring(二) AOP之AspectJ框架的使用
前面讲解了spring的特性之一,IOC(控制反转),因为有了IOC,所以我们都不需要自己new对象了,想要什么,spring就给什么.而今天要学习spring的第二个重点,AOP.一篇讲解不完,所以 ...
- Spring 的AOP底层实现技术:JDK和CGLIB动态代理
Spring 的AOP实现技术之JDK的动态代理技术实例: 接口:IUserService (Spring的AOP是动态AOP,实现技术:JDK提供的动态代理和cglib代理,cglib它可以为没有实 ...
- Spring AOP学习笔记01:AOP概述
1. AOP概述 软件开发一直在寻求更加高效.更易维护甚至更易扩展的方式.为了提高开发效率,我们对开发使用的语言进行抽象,走过了从汇编时代到现在各种高级语言繁盛之时期:为了便于维护和扩展,我们对某些相 ...
- Spring技术内幕总结 - AOP概述
AOP是Aspect-Oriented Programming(面向方面/切面编程)的简称.Aspect是一种新的模块化机制,用来描述分散在对象.类或函数中的横切关注点.分离关注点使解决特定领域问题的 ...
- Spring框架的核心功能之AOP概述
1. 什么是AOP的技术? * 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程 * AOP是一种编程范式,隶属于软工范畴,指导开发者如何组织程序结构 ...
- Spring之二:Spring AOP概述
一.AOP概念回顾 AOP是Aspect-Oriented Programming(面向方面编程)的简称, 虽然可以利用面向对象的方法可以很好地组织代码,也可以通过继承关系实现代码重用,但是程序中总是 ...
- Spring源码剖析6:Spring AOP概述
原文出处: 五月的仓颉 我们为什么要使用 AOP 前言 一年半前写了一篇文章Spring3:AOP,是当时学习如何使用Spring AOP的时候写的,比较基础.这篇文章最后的推荐以及回复认为我写的对大 ...
- Spring:AOP面向切面编程
AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果. AOP是软件开发思想阶段性的产物,我们比较熟悉面向过程O ...
- Spring框架第五篇之Spring与AOP
一.AOP概述 AOP(Aspect Orient Programming),面向切面编程,是面向对象编程OOP的一种补充.面向对象编程是从静态角度考虑程序的结构,而面向切面编程是从动态角度考虑程序运 ...
随机推荐
- 21.栈的压入、弹出序列 Java
题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压 ...
- springboot多个数据源
1.启动两个mysql,可以按照如下操作使用docker来部署mysql容器,比较简单 https://www.cnblogs.com/qq931399960/p/11527222.html 2.如果 ...
- CentOS7 源码安装 PostgreSQL 12
PostgreSQL 12 源码安装 Table of Contents 1. 下载 2. 准备环境 3. 编译安装 4. 设置环境变量 5. 初始化数据库 6. 配置参数文件 6.1. postgr ...
- React Native真机红屏报错总结
一.run-android报错:unable to load script from assets 'index.android.bundl' 解决: 1.进入\android\app\src\mai ...
- .SpringIOC容器
创建对象 SpringIOC容器,是spring核心内容. 作用: 创建对象 & 处理对象的依赖关系 IOC容器创建对象: 创建对象, 有几种方式: 1) 调用无参数构造器 2) 带参数构造器 ...
- 转 CentOS 7 环境下安装Maven
下载安装文件 wget http://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.3.9/binaries/apache-maven-3.3 ...
- 小D课堂 - 新版本微服务springcloud+Docker教程_5-05熔断降级服务异常报警通知
笔记 5.熔断降级服务异常报警通知实战 简介:完善服务熔断处理,报警机制完善 1.加入redis依赖 <dependency> <gr ...
- 一百零四:CMS系统之修改邮箱界面
在base.css中加一个全局的css控制宽度 .form-container{ width: 300px;} 视图 class ResetEmailView(views.MethodView): d ...
- [ML] Feature Transformers
方案选择可参考:[Scikit-learn] 4.3 Preprocessing data 代码示范可参考:[ML] Pyspark ML tutorial for beginners 本篇涉及:Fe ...
- Python 常用模块(2) 序列化(pickle,shelve,json,configpaser)
主要内容: 一. 序列化概述 二. pickle模块 三. shelve模块 四. json模块(重点!) 五. configpaser模块 一. 序列化概述1. 序列化: 将字典,列表等内容转换成一 ...