Spring AOP 介绍与基于接口的实现
热烈推荐:超多IT资源,尽在798资源网
声明:转载文章,为防止丢失所以做此备份。
本文来自公众号:程序之心
原文地址:https://mp.weixin.qq.com/s/vo94gVyTss0LYwEcRx4iiw
面向切面编程,缩写为 AOP,在程序开发中主要用来解决一些系统层面上的问题,比如日志、事务、权限等。在阿里体系中,AOP
广泛应用于天梭日志、本地缓存、doom 增强等场景。
AOP基本概念
为什么需要面向切面编程?面向对象编程解决了封装问题,但同时也带来了新问题,如何增强对象的方法?比如,一个接口 A 可能有多个实现类 A1、A2、******、An,如何为多个实现类的同一个方法打印日志或者做权限管理?普通的面向对象思路一般是封装一个工具类,然后加到所有方法里,一旦需要做的增强比较多代码就会很臃肿,难以维护。因此,才有了面向切面编程。
下面的图展示了面向切面编程的思想,面向对象编程通过封装、继承和多态实现了业务逻辑,而面向切面编程把业务流程横刀切开在切面上处理特定事务。一横一竖,切面的称呼就是这样来的。

从上图也可以看出面向切面编程不属于业务逻辑的一部分,而是与具体业务无关的特定事务,如日志、权限等。面向切面编程有以下几个概念需要理解:
- (1)Aspect(切面):通常是一个类,里面可以定义切入点和通知;
- (2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用;
- (3)Advice(通知):AOP在特定的切入点上执行的增强处理,可以是前置处理、后置处理、异常处理等;
- (4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式;
- (5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。
- (6)织入:把切面应用到目标对象来创建新的代理对象的过程。
织入一般发生在如下几个时机:
- (1)编译时:当一个类文件被编译时进行织入,这需要特殊的编译器才可以做的到,例如AspectJ的织入编译器;
- (2)类加载时:使用特殊的ClassLoader在目标类被加载到程序之前增强类的字节代码;
- (3)运行时:切面在运行的某个时刻被织入。
Spring AOP
Spring 提供了专门的依赖包来支持 AOP 。Spring中的AOP代理可以是JDK动态代理,也可以是CGLIB代理。代理的生成,管理及其依赖关系都是由IOC容器负责,Spring默认使用JDK动态代理,在需要代理类而不是代理接口的时候,Spring会自动切换为使用CGLIB代理。
Spring 提供了多种实现AOP的方式:
- 基于接口实现的切面:实现接口的方法,定义切入点和通知;
- 基于注解的切面:基于 @Aspect、@Pointcut、@Before、@AfterReturning 等注解的 AOP 方式;
- 基于 XML 的切面:使用 xml 中的 aop 命名空间,如 aop:aspect;
这里介绍使用比较多比较简单的基于接口方式,其他几种类型不做介绍。Spring 使用 Advisor 接口表示一般切面,包含了 Advice,但是没有切入点。
public interface Advisor {
//获取 Advice
Advice getAdvice();
//暂不用
boolean isPerInstance();
}
PointcutAdvisor 接口继承了 Advisor,代表具有切入点的切面,它包含Advice 和 Pointcut 两个类。基于 PointcutAdvisor 接口即可定义切面,可以通过类、方法名、注解等信息灵活地定义切面的连接点,提供更具适用性的切面。
public interface PointcutAdvisor extends Advisor {
//获取 Pointcut
Pointcut getPointcut();
}
Spring 提供了 PointcutAdvisor 接口的 6 个实现类,定义了 6 种切面类型,如下:
- DefaultPointcutAdvisor:最常用的切面类型,它可以通过任意Pointcut和Advice定义一个切面;
- NameMatchMethodPointcutAdvisor:通过该类可以定义按方法名定义切点的切面:
- RegexpMethodPointcutAdvisor:对于按正则表达式匹配方法名进行切点定义的切面,可以通过扩展该实现类进行操作;
- StaticMethodMatcherPointcutAdvisor:静态方法匹配器切点定义的切面;
- AspecJExpressionPointcutAdvisor:用于Aspecj切点表达式定义切点的切面;
- AspecJPointcutAdvisor:用于AspecJ语法定义切点的切面。
Spring AOP 提供了 Pointcut 接口多种内置实现,我们可以基于这些实现定义切入点。常用的实现包括:
- StaticMethodMatcherPointcut:静态匹配方法,实现方法级别的切入,非运行时切入,默认情况下匹配所有的类;
- DynamicMethodMatcherPointcut:动态匹配方法,实现方法级别的切入,运行时切入,默认情况下匹配所有的类;
- AnnotationMatchingPointcut:基于注解匹配;
- ExpressionPointcut:支持AspectJ切点表达式语法;
- ControlFlowPointcut:控制流程切点,根据程序执行堆栈的信息查看目标方法是否由某一个方法直接或间接发起调用,以此判断是否为匹配的连接点;
- ComposablePointcut:复合切点,为创建多个切点而提供的方便操作类。它所有的方法都返回ComposablePointcut类,这样,我们就可以使用链接表达式对其进行操作。
Spring AOP 提供了 Advice 接口多个子接口来支持增强。如下所示:
- 接口 MethodBeforeAdvice:在目标方法调用之前调用的Advice;
- 接口 AfterReturningAdvice:在目标方法调用并返回之后调用的Advice;
- 接口 MethodInterceptor:在目标方法的整个执行前后有效,并且有能力控制目标方法的执行;
- 接口 ThrowsAdvice:在目标方法抛出异常时调用的Advice;
基于接口的AOP使用方式
基于 PointcutAdvisor 接口实现 AOP 只需要定义切入点 Pointcut 和通知 Advice 即可,其他交给 Spring AOP 框架去处理。在基于接口的实现中,PointcutAdvisor 的实现类定义了一个切面。
在 getPointcut 中定义切入点。如下面的示例,定义了切入点是所有拥有 MyTestAnnotation 注解的方法,凡是有注解的方法都是我们的切入点。
@Getter
public Pointcut pointcut = new StaticMethodMatcherPointcut() {
@Override
public boolean matches(Method method, Class<?> targetClass) {
return method.getAnnotation(MyTestAnnotation.class) != null;
}
};
在 getAdvice() 中定义需要做的增强。如下面的示例,实现了 MethodInterceptor 接口来进行方法增强,入参为 MethodInvocation 对象,该对象携带了切面的信息,如正在调用的方法、入参等。可以在方法中直接调用原来的方法,并在调用方法前进行前置处理,或者在调用方法后进行后置处理。
@Getter
public Advice advice = (MethodInterceptor)methodInvocation -> {
// TODO 增强前置处理
// 调用原来的方法
Object result = methodInvocation.proceed();
// TODO 增强后置处理
return result;
};
AOP注意事项
- AOP 不宜处理耗时太久的操作:AOP 作为切面应该专注于处理简单的事务,如打印日志。耗时过多的操作不宜放在 AOP
中进行,如果一定需要处理,应该做异步处理。 - AOP 不宜抛出异常:AOP 的操作不能影响正常的业务逻辑,因此一定要加 catch,确保 AOP 本身的异常不影响正常业务。
- AOP 不能出现循环:尤其是打印日志的切面,一定要避免循环。AOP 中出现错误需要打印日志的时候,尽量单独打印,避免循环。
总结
本文介绍了 AOP 基本概念,介绍了基于 Spring AOP 接口实现面向切面编程的方法。
合理地使用 AOP 可以降低系统复杂度,无侵入地增强系统的功能,在 Java 企业应用中有着广泛的应用。
Spring AOP 介绍与基于接口的实现的更多相关文章
- Spring AOP介绍与使用
Spring AOP介绍与使用 AOP:Aspect Oriented Programming 面向切面编程 OOP:Object Oriented Programming 面向对象编程 面向切面 ...
- Spring AOP介绍
1.介绍 AOP(面向切面编程)对OOP(面向对象编程)是一种补充,它提供了另一种程序结构的思路.OOP的模块单元是class,而AOP的模块单元是aspect.Spring中一个关键的组件是AOP框 ...
- Spring AOP介绍及源码分析
转自:http://www.uml.org.cn/j2ee/201301102.asp 软件开发经历了从汇编语言到高级语言和从过程化编程到面向对象编程:前者是为了提高开发效率,而后者则使用了归纳法,把 ...
- spring aop介绍和示例
参考:<Spring in Action> 一.AOP介绍 AOP是Aspect Oriented Programming的缩写,意思是面向切面编程. 应用中有一些功能使用非常普遍,比如事 ...
- Spring AOP 创建Advice 基于Annotation
public interface IHello { public void sayHello(String str); } public class Hello implements IHello { ...
- Spring Aop(十五)——Aop原理之Advised接口
转发地址:https://www.iteye.com/blog/elim-2398726 Spring Aop原理之Advised接口 通过之前我们介绍的ProxyFactory我们知道,Spring ...
- Spring Aop(七)——基于XML配置的Spring Aop
转发:https://www.iteye.com/blog/elim-2396043 7 基于XML配置的Spring AOP 基于XML配置的Spring AOP需要引入AOP配置的Schema,然 ...
- 基于代理类实现Spring AOP
目录 ProxyFactoryBean类介绍 基于JDK动态代理的Spring AOP实现 基于CGLIB代理的Spring AOP实现 Spring的通知类型 ProxyFactoryBean类 ...
- Spring AOP 和 动态代理技术
AOP 是什么东西 首先来说 AOP 并不是 Spring 框架的核心技术之一,AOP 全称 Aspect Orient Programming,即面向切面的编程.其要解决的问题就是在不改变源代码的情 ...
随机推荐
- Selenium调用JavaScript修改元素属性
修改元素的style,主要是将一些隐性元素显示出来,让元素可被操作: JavascriptExecutor js = (JavascriptExecutor)driver; js.executeSc ...
- SVN提示被锁定的解决方法(转)
1.(常用)出现这个问题后使用“清理”即"Clean up"功能,如果还不行,就直接到上一级目录,再执行“清理”,然后再“更新”. 2.(没试过)有时候如果看到某个包里面的文件夹没 ...
- [React] Forward a DOM reference to another Component using forwardRef in React 16.3
The function forwardRef allows us to extract a ref and pass it to its descendants. This is a powerfu ...
- # 从零開始搭建Hadoop2.7.1的分布式集群
Hadoop 2.7.1 (2015-7-6更新),Hadoop的环境配置不是特别的复杂,可是确实有非常多细节须要注意.不然会造成很多配置错误的情况.尽量保证一次配置正确防止重复改动. 网上教程有非常 ...
- DexClassLoader和PathClassLoader类载入机制
0x00 在DexClassLoader和PathClassLoader载入Dex流程一文中,我们分析了dex文件怎样形成了DexFile结构体.本文中解说类载入机制,实际上就是生成ClassObje ...
- 深度学习将会变革NLP中的中文分词——TODO 待好好细看
见:https://www.leiphone.com/news/201608/IWvc75oJglAIsDvJ.html TODO 待好好细看
- [POJ 1639] Picnic Planning
[题目链接] http://poj.org/problem?id=1639 [算法] 首先,我们可以用深度优先遍历求出1号节点去除后有几个联通块 设共有T个联通块,若T > K则无解,否则 : ...
- Gym-101915D Largest Group 最大独立集 Or 状态压缩DP
题面题意:给你N个男生,N个女生,男生与男生之间都是朋友,女生之间也是,再给你m个关系,告诉你哪些男女是朋友,最后问你最多选几个人出来,大家互相是朋友. N最多为20 题解:很显然就像二分图了,男生一 ...
- CSS Flexbox 弹性盒子模型
CSS Flexbox 弹性盒子模型 设置元素样式为 display: flex 或 display: inline-flex, 让元素变成flex容器, 从而可以通过flex模式布局它的子元素. f ...
- QlikSense系列(3)——QlikSense建立数据模型
QlikSense管理数据在帮助中写的比较清楚 https://help.qlik.com/zh-CN/sense/3.1/Subsystems/Hub/Content/LoadData/load-d ...