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. Zookeeper系列(十四)Zookeeper的数据与存储

    作者:leesf    掌控之中,才会成功:掌控之外,注定失败. 出处:http://www.cnblogs.com/leesf456/p/6179118.html尊重原创,奇文共欣赏: 一.前言 前 ...

  2. IDEA checkout Git 分支 弹出 Git Checkout Problem

    1. 本地分支切换的时候(例如A切到B),会弹出来Restore workspace on branch switching 对话框,如果选择是的话,在切换分支的时候,你在当前分支(A)所做的一些还未 ...

  3. 14.链表中倒数第k个结点 Java

    题目描述 输入一个链表,输出该链表中倒数第k个结点. 思路 快指针和慢指针,快指针先跑K个单位然后慢指针开始跑,快指针跑到最后一个节点的时候慢指针对应的就是链表中倒数第k个结点 public stat ...

  4. 本地访问weblogic控制台无反应,关闭linux操作系统防火墙

    有时候,我们在Linux操作系统上成功启动了weblogic,也查看了7001端口的状态是开启的.但是访问weblogic控制台没有反应,也没有报错. 使用 netstat -ano | grep 7 ...

  5. Linux设备驱动程序 之 并发及其管理

    竞态产生 Linux系统找那个存在大量的并发联系,因此会导致可能的竞态: 1. 正在运行的用户空间进程可以以多种组合方式访问我们的代码: 2. SMP系统甚至可以再不同的处理器上同时执行我们的代码: ...

  6. 计数原理,递推,求从左边能看到l个棒子,右边能看到r个棒子的方案数目

    题意 有高为 1, 2, …, n 的 n 根杆子排成一排, 从左向右能看到 L 根, 从右向左能看到 R 根.求有多少种可能的排列方式.   solution: 数据范围仅200,本来是往组合数学方 ...

  7. Android屏幕横竖屏切换和生命周期管理的详细总结

    一般的我们去切换屏幕方向都是不希望Activity被重新创建,这时就需要对一些属性进行设置,或者使用代码设置.        今天想学一下Android屏幕横竖屏切换,但是网上很多知识不准确或不正确, ...

  8. [go]redis基本使用

    redis 数据结构操作 import ( "github.com/garyburd/redigo/redis" ) // set c, err := redis.Dial(&qu ...

  9. Selenium 2自动化测试实战34(编写Web测试用例)

    编写Web测试用例 1.介绍了unittest单元测试框架,其主要是来运行Web自动化测试脚本.简单的规划一下测试目录:web_demo1/------test_case/------------te ...

  10. Linux新增开放端口

    CentOS系统 开放端口的方法: 方法一:命令行方式               1. 开放端口命令: /sbin/iptables -I INPUT -p tcp --dport 8080 -j ...