spring源码之AOP上篇
概述
AOP,面向切面编程,通过预编译或者动态代理的方式实现程序公共功能维护的技术。这里的公共功能指的就是我们平常所说的横切关注点,在系统开发中我们可以将关注点划分为核心关注点与横切关注点。
- 核心关注点:核心关注点上在需求分析时,根据不同的业务需求划分出来的不同模块,用来完成业务逻辑处理。
- 横切关注点:对于那些与业务逻辑不相关的、核心关注点共同需要的关注点,比如日志,事务,权限认证这些我们就是我们的的横切关注点。
明白了横切关注点,下面来聊聊OOP与AOP。
编程的历史长河中,提出了各种方法和设计原则,都是用来保障系统的可复用性与可扩展性,以期建立一个松散耦合、便于扩展的软件系统,OOP与AOP也是一样。
在我们初学C的时候,习惯把所有的代码都写进一个main函数,当系统变大时,维护起来就很不方便。我们想到用子函数对程序进行模块划分和功能封装,这样维护起来只要关注自己的“一亩三分地”。在我们刚学习java的时候,
就知道它一门OOP的语言,它把数据与处理方法放在一起-让计算尽可能靠近数据。与子函数相比,OOP的模块化就更完备了。OOP帮我们更好地组织了代码,通过继承可以实现代码的复用。但是呢,程序中还会出现许多重复的代码,
于是我们通过公共函数对这些重复代码做一些封装,但是出现了两个问题
- 需要我们进行显式调用,使用上不灵活
- 维护起来还是比较麻烦
这个时候AOP来了,所以说AOP是OOP的延伸。在我们使用spring的AOP时,只需要在配置文件中进行配置,就能完成调用,相当灵活,耦合度很低。关于两者的区别,可以从以下两点进行把握
- OOP是对现实世界的实体进行抽象,是名字领域;AOP是对业务处理过程的某个步骤的抽象,是动词领域
- OOP通过继承、多态来建立一种对象层次结构;AOP通过静态编织或者动态织入的方式,来定义一种从左到右的关系。
知识点
在进行源码分析之前,先需要理解先个概念
- 通知:通知定义了织入的工作(比如记录日志)和何时进行工作(比如调用之前、调用之后)
- Before:方法调用之前,对应spring的<aop:before>
- After:方法完成之后,无论执行是成功还是失败,对应spring的<aop:after>
- After-returning:方法执行成功之后、返回之前,对应spring的<after-returning>
- After-throwing:方法抛出异常之后,对应spring的<aop:after-throwing>
- Around:方法执行前后,对应spring的<aop:around>
- 切点:切点定义了何处进行织入,在spring通过<aop:pointcut>中的表达式来定义,其实对应的就是一系列的方法
- 连接点:切点定义了何处,切点表达式能够匹配到每一处就是一个连接点,其实就是一个方法封装成了一个JoinPoint对象,我们可以通过JoinPoint对象拿到方法的相关信息
- 切面:通知+切点就是我们的切面。定义的何处何时做什么。对应spring中的<aop:aspect>
- 织入时期
- 源码编码成class的过程,要求特殊的编码器,比如AspectJ的织入编译器
- class加载到JVM中的过程,需要特殊的类加载器,比如AspectJ5 的 LTW
- 运行期生成代理对象,比如spring
Spring中的配置
在spring使用AOP时,我们一般使用两种方式:注解方式和XML配置方式
- XML方式
- 注解方式
使用注解时,一定要先打开AOP的自动代理
总结
- spring中对AspectJ提供了支持,这块没有去研究过
- 这篇只是对一些基础概念和常用的两种使用方式进行说明,下篇深入到spring aop的源码
参考链接
- https://wenku.baidu.com/view/6ce3121da300a6c30c229f89.html(核心关注点与横切关注点)
- https://www.cnblogs.com/syf/archive/2012/05/09/2491780.html(OOP与AOP)
- https://blog.csdn.net/garfielder007/article/details/78057107(连接点用地概念)
- https://docs.spring.io/spring/docs/4.3.18.RELEASE/spring-framework-reference(spring官方文档)