在介绍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. PHP生成HTML静态页面。

    function Generate(){ $html = '<!DOCTYPE html><html lang="en"><head> < ...

  2. IDEA常用快捷键,收藏以备后用

    IntelliJ Idea 常用快捷键列表 Ctrl+Shift + Enter,语句完成“!”,否定完成,输入表达式时按 “!”键Ctrl+E,最近的文件Ctrl+Shift+E,最近更改的文件Sh ...

  3. idea导入项目

    1. 2.导入项目 3.右键项目选择web 4.编辑添加tomcat 5.添加jar.包 6. 7.右键put into 8.安装tomcat 9.引入tomcat 10.把项目布署到tomcat

  4. 目标检测之faster-RCNN和FPN

    今年(2017年第一季度),何凯明大神出了一篇文章,叫做fpn,全称是:feature pyramid network for object Detection,为什么发这篇文章,根据 我现在了解到的 ...

  5. R语言-箱型图&热力图

    1.箱型图 boxplot()函数 > metals<-read.csv("metals.csv",header=TRUE) #读取文件和列名 > boxplot ...

  6. 正确理解c和c ++的复杂类型声明

    本文作者girlrong是网易广州社区的C语言版版主,这篇文章被选在精华区.很是不错,不敢独享!据说她乐于助人,虚心诚恳,颇受网友欢迎.只可惜现在已退隐江湖了.在最近学习C语言过程中,了解些前辈大牛的 ...

  7. gdbserver

    这里写下gdbserver的用法: 两台机子,宿主机A和目标机B. step1: 我们在B上安装gdbserver,在A上编译可执行程序a.out,把a.out拷贝到B上面去. step2: 在A上打 ...

  8. uvm_pre_do

    https://blog.csdn.net/tingtang13/article/details/46535649 1.uvm_do 封装了一系列接口,封装越多,灵活性越差.所以增加了三个接口:pre ...

  9. pipeline-安全测试

    代码安全检查 需要安装SonarQube(版本6.7,安装了Findbugs插件) MySQL >=5.6,笔者安装的是MySQL 5.7版本 Jenkins需要安装下列插件: SonarQub ...

  10. oracle 执行顺序 select查询优化

    今天把这几天做的练习复习了一下,不知道自己写得代码执行的效率如何以及要如何提高,于是乎上网开始研究一些材料,现整理如下: 首先,要了解在Oracle中Sql语句运行的机制.以下是sql语句的执行步骤: ...