前言
上一篇已经讲解了Spring IOC知识点一网打尽!,这篇主要是讲解Spring的AOP模块~
之前我已经写过一篇关于AOP的文章了,那篇把比较重要的知识点都讲解过了一篇啦:Spring【AOP模块】就这么简单,很荣幸被开源中国推荐过~~
- 如果没有AOP的基础,建议先看看上面那篇文章~
- 如果没有代理模式基础,建议先看看:给女朋友讲解什么是代理模式这篇文章
- 如果都看过了,这篇就放心食用吧!
这篇文章主要是补充和强化一些比较重要的知识点,并会把上面的两本书关于AOP的知识点整理出来并画成一个思维导图来全面了解Spring AOP的知识点!
那么接下来就开始吧,如果有错的地方希望能多多包涵,并不吝在评论区指正!
一、Spring AOP全面认知
结合《Spring 实战 (第4版)》和《精通Spring4.x 企业应用开发实战》两本书的AOP章节将其知识点整理起来~
1.1AOP概述
AOP称为面向切面编程,那我们怎么理解面向切面编程??
我们可以先看看下面这段代码:
我们学Java面向对象的时候,如果代码重复了怎么办啊??可以分成下面几个步骤:
- 1:抽取成方法
- 2:抽取类
抽取成类的方式我们称之为:纵向抽取
- 通过继承的方式实现纵向抽取
但是,我们现在的办法不行:即使抽取成类还是会出现重复的代码,因为这些逻辑(开始、结束、提交事务)依附在我们业务类的方法逻辑中!
现在纵向抽取的方式不行了,AOP的理念:就是将分散在各个业务逻辑代码中相同的代码通过横向切割的方式抽取到一个独立的模块中!
上面的图也很清晰了,将重复性的逻辑代码横切出来其实很容易(我们简单可认为就是封装成一个类就好了),但我们要将这些被我们横切出来的逻辑代码融合到业务逻辑中,来完成和之前(没抽取前)一样的功能!这就是AOP首要解决的问题了!
1.2Spring AOP原理
被我们横切出来的逻辑代码融合到业务逻辑中,来完成和之前(没抽取前)一样的功能
没有学Spring AOP之前,我们就可以使用代理来完成。
- 如果看过我写的给女朋友讲解什么是代理模式这篇文章的话,一定就不难理解上面我说的那句话了
- 代理能干嘛?代理可以帮我们增强对象的行为!使用动态代理实质上就是调用时拦截对象方法,对方法进行改造、增强!
其实Spring AOP的底层原理就是动态代理!
来源《精通Spring4.x 企业应用开发实战》一段话:
Spring AOP使用纯Java实现,它不需要专门的编译过程,也不需要特殊的类装载器,它在运行期通过代理方式向目标类织入增强代码。在Spring中可以无缝地将Spring AOP、IoC和AspectJ整合在一起。
来源《Spring 实战 (第4版)》一句话:
Spring AOP构建在动态代理基础之上,因此,Spring对AOP的支持局限于方法拦截。
在Java中动态代理有两种方式:
- JDK动态代理
- CGLib动态代理
JDK动态代理是需要实现某个接口了,而我们类未必全部会有接口,于是CGLib代理就有了~~
- CGLib代理其生成的动态代理对象是目标类的子类
- Spring AOP默认是使用JDK动态代理,如果代理的类没有接口则会使用CGLib代理。
那么JDK代理和CGLib代理我们该用哪个呢??在《精通Spring4.x 企业应用开发实战》给出了建议:
- 如果是单例的我们最好使用CGLib代理,如果是多例的我们最好使用JDK代理
原因:
- JDK在创建代理对象时的性能要高于CGLib代理,而生成代理对象的运行性能却比CGLib的低。
- 如果是单例的代理,推荐使用CGLib
看到这里我们就应该知道什么是Spring AOP(面向切面编程)了:将相同逻辑的重复代码横向抽取出来,使用动态代理技术将这些重复代码织入到目标对象方法中,实现和原来一样的功能。
- 这样一来,我们就在写业务时只关心业务代码,而不用关心与业务无关的代码
1.3AOP的实现者
AOP除了有Spring AOP实现外,还有著名的AOP实现者:AspectJ,也有可能大家没听说过的实现者:JBoss AOP~~
我们下面来说说AspectJ扩展一下知识面:
AspectJ是语言级别的AOP实现,扩展了Java语言,定义了AOP语法,能够在编译期提供横切代码的织入,所以它有专门的编译器用来生成遵守Java字节码规范的Class文件。
而Spring借鉴了AspectJ很多非常有用的做法,融合了AspectJ实现AOP的功能。但Spring AOP本质上底层还是动态代理,所以Spring AOP是不需要有专门的编辑器的~
1.4AOP的术语
嗯,AOP搞了好几个术语出来~~两本书都有讲解这些术语,我会尽量让大家看得明白的:
连接点(Join point):
- 能够被拦截的地方:Spring AOP是基于动态代理的,所以是方法拦截的。每个成员方法都可以称之为连接点~
切点(Poincut):
- 具体定位的连接点:上面也说了,每个方法都可以称之为连接点,我们具体定位到某一个方法就成为切点。
增强/通知(Advice):
- 表示添加到切点的一段逻辑代码,并定位连接点的方位信息。
- 简单来说就定义了是干什么的,具体是在哪干
- Spring AOP提供了5种Advice类型给我们:前置、后置、返回、异常、环绕给我们使用!
织入(Weaving):
- 将
增强/通知
添加到目标类的具体连接点上的过程。
引入/引介(Introduction):
引入/引介
允许我们向现有的类添加新方法或属性。是一种特殊的增强!
切面(Aspect):
- 切面由切点和
增强/通知
组成,它既包括了横切逻辑的定义、也包括了连接点的定义。
在《Spring 实战 (第4版)》给出的总结是这样子的:
通知/增强包含了需要用于多个应用对象的横切行为;连接点是程序执行过程中能够应用通知的所有点;切点定义了通知/增强被应用的具体位置。其中关键的是切点定义了哪些连接点会得到通知/增强。
总的来说:
- 这些术语可能翻译过来不太好理解,但对我们正常使用AOP的话影响并没有那么大~~看多了就知道它是什么意思了。
1.5Spring对AOP的支持
Spring提供了3种类型的AOP支持:
- 基于代理的经典SpringAOP
- 需要实现接口,手动创建代理
- 纯POJO切面
- 使用XML配置,aop命名空间
@AspectJ
注解驱动的切面
- 使用注解的方式,这是最简洁和最方便的!
二、基于代理的经典SpringAOP
这部分配置比较麻烦,用起来也很麻烦,这里我就主要整理一下书上的内容,大家看看了解一下吧,我们实际上使用Spring AOP基本不用这种方式了!
首先,我们来看一下增强接口的继承关系图:
可以分成五类增强的方式:
Spring提供了六种的切点类型:
切面类型主要分成了三种:
- 一般切面
- 切点切面
- 引介/引入切面
一般切面,切点切面,引介/引入切面介绍:
对于切点切面我们一般都是直接用就好了,我们来看看引介/引入切面是怎么一回事:
- 引介/引入切面是引介/引入增强的封装器,通过引介/引入切面,可以更容易地为现有对象添加任何接口的实现!
继承关系图: