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)来创建新的代理对象的过程。

比如将权限校验应用到 UserDaoImplsave 方法的这个过程。

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 动态代理是对实现接口类实行代理,建立一个实现目标类中方法的代理类。(面向接口)

具体代码:MyJdkProxy.java

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 只支持方法连接点,不提供属性连接

具体代码:MyCglibProxy.java


附:

spring 核心包有四个:

  • spring-context
  • spring-beans
  • spring-expression
  • spring-core

Spring 的 AOP 概述和底层实现的更多相关文章

  1. spring(二) AOP之AspectJ框架的使用

    前面讲解了spring的特性之一,IOC(控制反转),因为有了IOC,所以我们都不需要自己new对象了,想要什么,spring就给什么.而今天要学习spring的第二个重点,AOP.一篇讲解不完,所以 ...

  2. Spring 的AOP底层实现技术:JDK和CGLIB动态代理

    Spring 的AOP实现技术之JDK的动态代理技术实例: 接口:IUserService (Spring的AOP是动态AOP,实现技术:JDK提供的动态代理和cglib代理,cglib它可以为没有实 ...

  3. Spring AOP学习笔记01:AOP概述

    1. AOP概述 软件开发一直在寻求更加高效.更易维护甚至更易扩展的方式.为了提高开发效率,我们对开发使用的语言进行抽象,走过了从汇编时代到现在各种高级语言繁盛之时期:为了便于维护和扩展,我们对某些相 ...

  4. Spring技术内幕总结 - AOP概述

    AOP是Aspect-Oriented Programming(面向方面/切面编程)的简称.Aspect是一种新的模块化机制,用来描述分散在对象.类或函数中的横切关注点.分离关注点使解决特定领域问题的 ...

  5. Spring框架的核心功能之AOP概述

    1. 什么是AOP的技术? * 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程 * AOP是一种编程范式,隶属于软工范畴,指导开发者如何组织程序结构 ...

  6. Spring之二:Spring AOP概述

    一.AOP概念回顾 AOP是Aspect-Oriented Programming(面向方面编程)的简称, 虽然可以利用面向对象的方法可以很好地组织代码,也可以通过继承关系实现代码重用,但是程序中总是 ...

  7. Spring源码剖析6:Spring AOP概述

    原文出处: 五月的仓颉 我们为什么要使用 AOP 前言 一年半前写了一篇文章Spring3:AOP,是当时学习如何使用Spring AOP的时候写的,比较基础.这篇文章最后的推荐以及回复认为我写的对大 ...

  8. Spring:AOP面向切面编程

    AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果. AOP是软件开发思想阶段性的产物,我们比较熟悉面向过程O ...

  9. Spring框架第五篇之Spring与AOP

    一.AOP概述 AOP(Aspect Orient Programming),面向切面编程,是面向对象编程OOP的一种补充.面向对象编程是从静态角度考虑程序的结构,而面向切面编程是从动态角度考虑程序运 ...

随机推荐

  1. 02 Anaconda的介绍,安装记以及使用

    目录 〇.序 Python是一种面向对象的解释型计算机程序设计语言,其使用,具有跨平台的特点,可以在Linux.macOS以及Windows系统中搭建环境并使用,其编写的代码在不同平台上运行时,几乎不 ...

  2. 【零基础】斯坦福四足机器人DIY指引

    可以后空翻的机器狗 近日斯坦福开源了一个四足机器人项目“Stanford Doggo”,“只需”3000美金就可以DIY一个能跳一米高兼后空翻的电子小狗,一段时间研究后我们写了这篇简单的指引帮助大家快 ...

  3. 20175329&20175313&20175318 2019-2020 《信息安全系统设计基础》实验一

    详见 https://www.cnblogs.com/xiannvyeye/p/11792152.html#%E4%B8%80%E5%AE%9E%E9%AA%8C%E5%86%85%E5%AE%B9

  4. LeetCode 131. 分割回文串(Palindrome Partitioning)

    题目描述 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串. 返回 s 所有可能的分割方案. 示例: 输入: "aab" 输出: [ ["aa" ...

  5. python监控wechat

    import osimport reimport shutilimport timeimport itchatfrom itchat.content import * # 说明:可以撤回的有文本文字. ...

  6. 配置默认编码为utf8

    修改/etc/my.cnf配置文件,在[mysqld]下添加编码配置,如下所示: [mysqld] character_set_server=utf8 init_connect='SET NAMES ...

  7. vs下qt的信号与槽实现

    实现主窗口中Add按钮的功能, 这一部分要特别注意,除了实现功能代码外,还需自己手动添加一些其他的代码(Qt Creator可以自动添加). 我们需要在2个地方添加代码. 第1个是在addressbo ...

  8. smaller programs should improve performance RISC(精简指令集计算机)和CISC(复杂指令集计算机)是当前CPU的两种架构 区别示例

    COMPUTER ORGANIZATION AND ARCHITECTURE DESIGNING FOR PERFORMANCE NINTH EDITION In this section, we l ...

  9. Jmeter联机负载时报错: connection refused to host localhost,nested exception is:java.net ConnectException:Connection refused:connect

    Jmeter联机负载时报错: connection refused to host localhost,nested exception  is:java.net ConnectException:C ...

  10. Hibernate 的一些注解配置

    网上参考资料很多,但总是不符合自身习惯,遂记录下来. 一对多的关系 如class与student的关系 class中 @OneToMany(mappedBy = "class") ...