热烈推荐:超多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 介绍与基于接口的实现的更多相关文章

  1. Spring AOP介绍与使用

    Spring AOP介绍与使用 AOP:Aspect Oriented Programming 面向切面编程 OOP:Object Oriented Programming 面向对象编程 ​ 面向切面 ...

  2. Spring AOP介绍

    1.介绍 AOP(面向切面编程)对OOP(面向对象编程)是一种补充,它提供了另一种程序结构的思路.OOP的模块单元是class,而AOP的模块单元是aspect.Spring中一个关键的组件是AOP框 ...

  3. Spring AOP介绍及源码分析

    转自:http://www.uml.org.cn/j2ee/201301102.asp 软件开发经历了从汇编语言到高级语言和从过程化编程到面向对象编程:前者是为了提高开发效率,而后者则使用了归纳法,把 ...

  4. spring aop介绍和示例

    参考:<Spring in Action> 一.AOP介绍 AOP是Aspect Oriented Programming的缩写,意思是面向切面编程. 应用中有一些功能使用非常普遍,比如事 ...

  5. Spring AOP 创建Advice 基于Annotation

    public interface IHello { public void sayHello(String str); } public class Hello implements IHello { ...

  6. Spring Aop(十五)——Aop原理之Advised接口

    转发地址:https://www.iteye.com/blog/elim-2398726 Spring Aop原理之Advised接口 通过之前我们介绍的ProxyFactory我们知道,Spring ...

  7. Spring Aop(七)——基于XML配置的Spring Aop

    转发:https://www.iteye.com/blog/elim-2396043 7 基于XML配置的Spring AOP 基于XML配置的Spring AOP需要引入AOP配置的Schema,然 ...

  8. 基于代理类实现Spring AOP

    目录 ProxyFactoryBean类介绍 基于JDK动态代理的Spring  AOP实现 基于CGLIB代理的Spring  AOP实现 Spring的通知类型 ProxyFactoryBean类 ...

  9. Spring AOP 和 动态代理技术

    AOP 是什么东西 首先来说 AOP 并不是 Spring 框架的核心技术之一,AOP 全称 Aspect Orient Programming,即面向切面的编程.其要解决的问题就是在不改变源代码的情 ...

随机推荐

  1. qtp12版本下载安装破解教程

    下载链接:https://download.csdn.net/download/weixin_41479750/11240466 下面是安装教程: 解压完成之后,双击运行setup.exe 之后点击运 ...

  2. POJ 3528

    三维凸包 /* 增量法求凸包.选取一个四面体,同时把它各面的方向向量向外,增加一个点时,若该点与凸包上的某些面的方 向向量在同一侧,则去掉那些面,并使某些边与新增点一起连成新的凸包上的面. */ #i ...

  3. 赵雅智_ListView_SimpleAdapter

    项目步骤 声明listView控件并获取显示的视图 获取显示的数据 设置显示的adapter 注冊点击事件 详细案例 实现效果: 查找的方法 public List<Map<String, ...

  4. nexus启动报错----->错误 1067: 进程意外终止。

    1.今天启动nexus报错: 2.错误信息 错误 1067: 进程意外终止. 3.检查发现我之前把jdk升级了.然而nexus之前指定的jdk将不再生效. 4.解决办法 找到nexus安装目录 修改b ...

  5. (hdoj 5137 floyd)How Many Maos Does the Guanxi Worth

    How Many Maos Does the Guanxi Worth Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 512000/5 ...

  6. oracle中关于删除表purge语句和闪回语句的基本使用

    语法: drop table ... purge; 例子:drop table test purge; purge是直接删除表,不保留到回收站,10G开始默认drop表式改名移动到回收站; 闪回(fl ...

  7. 【HAOI 2008】 移动玩具

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1054 [算法] 广度优先搜索 [代码] #include<bits/stdc+ ...

  8. java中的数组的Arrays工具类的使用

    package day04.d1.shuzu; import java.util.Arrays; /** * Arrays 工具类 * @author Administrator * */public ...

  9. C# How to convert MessageBodyStream to MemoryStream?

    通过WCF服务从数据库取文档数据时,返回的是Stream对象,在DevExpress的PDFViewer显示时,用PDFViewer.LoadDocunent(Stream stream);方法时,报 ...

  10. WPF 漏斗控件 等待沙漏效果

    由于WPF中不支持gif图片因此要实现一个漏斗沙漏效果有点小麻烦. 网上有一款开源的控件 理论上完全开源 官网 http://wpfspark.codeplex.com/贴一下效果图 大家感觉需要就在 ...