在介绍AOP之前,想必很多人都听说AOP是基于动态代理和反射来实现的,那么在看AOP之前,你需要弄懂什么是动态代理和反射及它们又是如何实现的。

想了解JDK的动态代理及反射的实现和源码分析,请参见下面三篇文章

那么接下里进入AOP的环节。

AOP即面向切面编程,刚学AOP的时候,单是各种AOP的概念都搞的有点懵,什么切面,切点,通知,织入、连接点、目标对象。。。。AOP的原理都没看呢,这些词语的意思就已经让人不想看了。本文将在实现AOP的时候,讲解我理解的这些AOP的术语,对应的AOP的代码和动作。

本文将先从AOP代码实现入手,然后分析AOP的底层代码及其原理。

一、AOP的Demo

如果我们把对象的继承关系看成纵向关系,就像一棵树,多个不同类的多个继承关系就相当于有一排的树。AOP的好处就在于,你想对这些树进行相同的操作时,这个时候,不用纵向的为每个树定义操作方法,你只需要横向的一刀切,给他们提供个共有的操作方法。

Spring的AOP是支持JDK的动态代理和Cglib的动态代理的。JDK的动态代理是针对接口的,而Cglib是针对类的。本文针对JDK的动态代理。

首先定义一个接口:起名字时候特意给这个接口名,带上了Interface,这样后面会更引人注意一些。接口很简单,里面一个抽象方法eat()

package com.weili.cn;
/**
* 动物接口,提供一个eat的抽象方法
* Created by zsqweilai on 17/6/27.
*/
public interface AnimalInterface {
   public abstract void eat();
}

实现类:作为一个吃货,实现类里面当然得打印 chi  chi  chi。撑死我吧!!!
这个实现类里面,只有一个方法,这个方法就是AOP的切点。虽然切点这个概念本身并不一定是Method,但在Spring中,所有的切点都是Method。我们增强的是方法。

切面类,又称增强类。因为我们是要用这个类的方法,来给原先的切点方法增强。切面类中,我们要去执行的方法,称为通知。所谓织入通知,就是将切面类里面的方法,和切点的方法进行联系。

接下来通过xml配置的方式,在xml文件里面配置AOP。
配置<aop:pointcut>的时候,通过expressi表达式,定义了com.weili.cn这个包下的所有类的所有方法 为切入点。也就是说,这个包下的所有方法,在调用执行的时候,会被Spring增强。具体在这里的增强,就是在执行这些切点方法之前和之后,会分别执行animalEmpty 和 animalFull方法。

最后就是调用的方法了。
我得说明一点,在我们进行spring-aop.xml解析的时候,aop还没实现呢。在第二行getBean的时候,才真正进行aop。具体的源码那里 会说明。

紧接着就是Output输出了。所以,我们可以看到,获取的bean,确实是增强后的bean。那么就赶紧看看源码吧。

二、AOP源码分析

源码解析这块,首先就是bean加载。之前也说了,AOP标签也是自定义标签,它的解析也和我们之前自定义标签一样,走自定义标签的解析流程。不同的是,AOP调用的是AOP自己的解析器。由于在 Spring源码解析之二 ------ 自定义标签的解析和注册 中已经很详细的描述了自定义标签的解析流程,所以这里我们就不再去一一看bean标签的解析注册。

所以AOP的源码分析,我们将从调用类里面的第二行,ctx.getBean("animal")开始。在你调试走到这里的时候,在ctx中可以看到解析和注册的bean,我们不妨先来看一下。

如下图,这个是在第一行代码执行完毕后,ctx的各个属性。可以在下图看到,singlentonObjects中,已经存放了代理生成的animal。生层bean的过程在之前的里面已经讲的比较清楚了,这里就不再说明。毕竟AOP嘛,我们需要知道,它是如何在我们需要执行的方法前后将我们需要执行的方法执行完成的。

ctx.getBean("animal")获取完animal bean后,接下来调用eat()方法。这个时候,会进入JdkDynamicAopProxy类的invoke方法。
在这个invoke方法中,先是获取代理类targetClass,然后根据method和targetClass获取此方法对应的拦截器执行链chain。

这个chain的内容如下。通过名字可以看到,一个是afterAdvice,一个是beforeAdvice。获取chain后,构造出一个MethodInvoke方法,然后执行proceed方法。

进入proceed方法。currentInterceptorIndex的初始化值为-1.紧接着就如invoke方法。这里的this是我们的eat方法。

在invoke方法里,这里的mi是我们的interface里面的eat方法。然后执行mi的proceed()方法。

这个时候,会继续回到开始时候的proceed方法。这个时候获取到的是

interceptorOrInterceptionAdvice,也就是前面拦截器的list里面的第二个,after的那个方法。然后继续递归调用,会到链表的最后一个before方法。
    最终会调用before里面的方法,

然后回去执行invokeJoinpoint方法,

Spring AOP的实现及源码解析的更多相关文章

  1. Spring核心框架 - AOP的原理及源码解析

    一.AOP的体系结构 如下图所示:(引自AOP联盟) 层次3语言和开发环境:基础是指待增加对象或者目标对象:切面通常包括对于基础的增加应用:配置是指AOP体系中提供的配置环境或者编织配置,通过该配置A ...

  2. Spring MVC工作原理及源码解析(三) HandlerMapping和HandlerAdapter实现原理及源码解析

    1.HandlerMapping实现原理及源码解析 在前面讲解Spring MVC工作流程的时候我们说过,前端控制器收到请求后会调⽤处理器映射器(HandlerMapping),处理器映射器根据请求U ...

  3. Spring IOC和Spring AOP的实现原理(源码主线流程)

    写在前面 正本文参考了<spring技术内幕>和spring 4.0.5源码.本文只描述原理流程的主线部分,其他比如验证,缓存什么可以具体参考源码理解. Spring IOC 一.容器初始 ...

  4. SpringBoot 源码解析 (八)----- Spring Boot 精髓:事务源码解析

    本篇来讲一下SpringBoot是怎么自动开启事务的,我们先来回顾一下以前SSM中是如何使用事务的 SSM使用事务 导入JDBC依赖包 众所周知,凡是需要跟数据库打交道的,基本上都要添加jdbc的依赖 ...

  5. 【SSH进阶之路】Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)

    我们前面的三篇博文,简单易懂的介绍了为什么要使用IOC[实例讲解](二).和Spring的IOC原理[通俗解释](三)以及依赖注入的两种常用实现类型(四),这些都是刚开始学习Spring IoC容器时 ...

  6. Spring MVC工作原理及源码解析(二)DispatcherServlet实现原理及源码解析

    1.DispatcherServlet 处理流程 从上一篇文章中Spring MVC原理图中我们可以看出:DispatcherServlet 在 Spring MVC框架 中处于核心位置,它负责协调和 ...

  7. 【spring源码学习】spring的事务管理的源码解析

    [一]spring事务管理(1)spring的事务管理,是基于aop动态代理实现的.对目标对象生成代理对象,加入事务管理的核心拦截器==>org.springframework.transact ...

  8. Spring MVC工作原理及源码解析(四) ViewResolver实现原理及源码解析

    0.ViewResolver原理介绍 根据视图的名称将其解析为 View 类型的视图,如通过 ModelAndView 中的视图名称将其解析成 View,View 是用来渲染页面的,也就是将 Mode ...

  9. Spring事件监听机制源码解析

    Spring事件监听器使用 1.Spring事件监听体系包括三个组件:事件.事件监听器,事件广播器. 事件:定义事件类型和事件源,需要继承ApplicationEvent. package com.y ...

随机推荐

  1. leetcode11

    public class Solution { //public int MaxArea(int[] height) //{ // var max = 0; // for (int i = 0; i ...

  2. 20165304第4次实验《Android程序设计》实验报告

    一.实验报告封面 课程:Java程序设计 班级:1653班 姓名:李松杨 学号:20165304 指导教师:娄嘉鹏 实验日期:2018年5月14日 实验时间:15:35 - 17:15 实验序号:实验 ...

  3. Navicat for MySQL使用

    Navicat for MySQL使用 导出数据库表与结构 新数据库导入

  4. ArcGIS自定义工具箱-修复损坏的工作空间

    ArcGIS自定义工具箱-修复损坏的工作空间 联系方式:谢老师,135-4855-4328,xiexiaokui#qq.com 目的:替换数据源的工作空间 用途:针对损坏的数据源,批量进行修复 案例数 ...

  5. C# WinForm窗体及其控件的自适应

    3步骤: 1.在需要自适应的Form中实例化全局变量   AutoSizeFormClass.cs源码在下方 AutoSizeFormClass asc = new AutoSizeFormClass ...

  6. layui-tree创建下拉树型选项框

    1.简介 也许你对树菜单再熟悉不过了,然而你仍有可能更青睐layui的tree,它也许比以往你知道的任何一个类似的组件都更轻量.简单,你在享受许多功能的同时,甚至不用去记太多的参数. 另外,最大的重点 ...

  7. ConcurrentModificationException并发修改异常

    //创建集合对象 Collection c = new ArrayList(); c.add("hello"); c.add("world"); c.add(& ...

  8. Selenium Webdriver元素定位的八种常用方式(转载)

    转载自 https://www.cnblogs.com/qingchunjun/p/4208159.html 在使用selenium webdriver进行元素定位时,通常使用findElement或 ...

  9. 《CSAPP》符号和符号表

    符号和符号表 每个可重定位目标模块m都有一个符号表,它包含m所定义和引用的符号的信息. 有三种不同的符号: 由m定义并能被其他模块引用的全局符号.对应非静态的C函数以及不带C static属性的全局变 ...

  10. c#: 界面多语言动态切换简单实现

    终于有空整理下多语言实现思路.查阅已有方案,有用不同resx文件的,有每个控件动态设置的,有用反射去整的,颇为繁琐. 结合项目中实现方法,并做简化,实现通用的多语言切换方案,以做备忘. 它支持语言自定 ...