AOP的定义:AOP(Aspect Oriented Progamming)利用称为"横切"的技术,剖解开封装的对象内部,把多个类的公共行为封装到一个可重用模块中,便于减少重复代码,降低模块之间的耦合度,符合“开闭原则”。

  上面这段关于AOP的定义是从网上抄的,是不是很拗口,我们就结合实际开发来先简单了解下AOP中的一些专业术语,然后再去学习使用它吧。

  在通常的业务开发中,我们往往只需要让业务逻辑去关注业务本身,但是一些复杂的业务我们为了保证数据的完整、后序发生问题之后能够快速定位问题,通常伴随着安全、日志、事务等代码,业务写多了我们发现这些代码通常都是类似的,那么我们不就可以将这些类似的代码封装起来,再需要使用的地方进行复用吗?AOP就为提供了这么一种思路,但是AOP中的一些专业术语特别拗口,我们在这简单总结下,做下记录方便后面的学习。

  1、通知(Advice):就是我们上面提到的除了业务代码本身之外,一些“可重用的一些代码”,先定义好,在需要的地方进行重用;

  2、连接点(JoinPoint):允许你使用“通知”的地方,就是允许你重复使用代码的地方,方法执行的前后或者方法抛出异常时,Spring只支持方法级别的连接点;

  3、切入点(Pointcut): 假如有若干方法,但是我们并不是想在所有的方法中“重用这段可复用的代码”,我们只想在某些特定的方法上使用通知,那么我们就可以使用切入点来进行这些连接点的“筛选了”;

  4、切面(Aspect):切面简单来讲就是切入点(JoinPoint)和通知(Advice)的结合体。通知(Advice)决定了要干什么(通知的方法体)?在什么时候干?(定义通知的注解类型)。而切入点决定了要在哪儿干(即执行通知定义的方法体)。

  5、引入(Introduction):允许我们向目标对象添加新的方法属性(即通过执行通知来控制对目标方法的访问);

  6、目标对象(Target):引入中所提到的目标对象,也就是要被通知的对象,也就是执行真正的业务逻辑,可以在毫不知情的情况下,织入我们的切面;

  7、代理(Proxy):Spring中的AOP都是通过动态代理来实现的,关于代理有不明白的可以参考设计模式之(8)——代理模式

   8、织入(Weaving):把切面应用到目标对象,创建代理对象的过程;

    9、AOP方法:通知+目标对象的方法。

  上面就是AOP编程中一些常用的属于,然后我们再看看AOP中最重要的通知(Advice)的分类,通知分为五类:

  为了方便下面理解,我们可以认为“连接点就是一个目标方法”。

  1、前置通知(Before Advice):在目标方法之前执行,前置通知不会影响目标方法的执行,除非前置通知抛出异常;

  2、正常返回通知(After Advice):在目标方法正常执行完成之后执行,如果目标方法抛出异常,则不会执行;

  3、异常返回通知(AfterThrowing Advice):在目标方法抛出异常之后会执行;

  4、返回通知(AfterReturning Advice):在目标方法执行完之后执行,不管目标方法是正常执行完,还是因为抛出异常退出,都会执行返回通知内的内容;

  5、环绕通知(Around Advice):环绕通知围绕在目标方法执行的前后,是一个功能最为强大的通知类型,可以在方法执行前后自定义一些操作,环绕通知还需要负责决定是继续处理join point(调用ProceedingJoinPoint的proceed方法)还是中断执行,为了避免后面的空指针,环绕通知还需要返回方法的执行结果。

  以下是我写的一个简单示例,通过一个自定义注解,来向需要的地方织入通知;

  自定义注解:

package com.pep.process.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
* @ClassName: Audit
* @Description: 描述这个类的作用
* @author: wwh
* @date: 2023年3月2日 上午9:47:52
*/ @Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Audit { String action() default ""; String name() default "";
}

  定义一个切面,切面中包含切入点和通知:

package com.pep.process.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component; /**
* @ClassName: AuditAop
* @Description: 自定义切面
* @author: wwh
* @date: 2023年3月2日 上午9:54:48
*/
@Component
@Aspect
public class AuditAspect { /**
* @Title: audit
* @Description: 定义一个切入点
* void 返回类型
*/
@Pointcut("@annotation(com.pep.process.annotation.Audit)")
private void audit() { } /**
* @Title: before
* @Description: 前置通知
* void 返回类型
*/
@Before("audit()")
public void before() {
System.err.println("我是前置通知...");
} /**
* @Title: around
* @Description: 环绕通知
* @param joinPoint
* @return
* Object 返回类型
*/
@Around("audit()")
public Object around(ProceedingJoinPoint joinPoint) {
try {
System.err.println("环绕通知执行前...");
Object proceed = joinPoint.proceed();
System.err.println("环绕通知执行后...");
return proceed;
} catch (Throwable e) {
e.printStackTrace();
System.err.println("目标方法执行过程中发生了异常...");
return null;
}
} /**
* @Title: after
* @Description: 描述这个方法的作用
* void 返回类型
*/
@After(value="audit()")
public void after() {
System.err.println("我是后置通知...");
} /**
* @Title: afterThrow
* @Description: 返回异常通知
* @param ex
* void 返回类型
*/
@AfterThrowing(value="audit()",throwing="ex")
public void afterThrow(Exception ex) {
System.err.println("异常通知...");
} /**
* @Title: afterReturning
* @Description: 返回通知
* @param obj
* @return
* Object 返回类型
*/
@AfterReturning(value="audit()",returning="obj")
public Object afterReturning(Object obj) {
System.err.println("我是返回通知...");
return obj;
}
}

  需要注意的是异常通知的注解中的throwing参数,通过这个参数,可以目标方法执行过程中抛出的异常,绑定到异常通知的方法参数中,并且这个参数值要和方法参数名称一致。

  同理返回通知注解中的returning参数,也是将目标方法的执行结果和返回通知中方法的参数进行绑定,名称也必须一致。

  通过使用自定义的方式来向需要的地方织入通知,实现方法功能“增强”或者控制方法访问。

package com.pep.process.controller;

import net.sf.json.JSONObject;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import com.pep.jxw.common.util.UUIDGenerator;
import com.pep.process.annotation.Audit; @Controller
public class LogController { @RequestMapping("/test.do")
@Audit
@ResponseBody
public JSONObject log() {
JSONObject json = new JSONObject();
json.put("id", UUIDGenerator.getUUID());
System.err.println("执行了目标方法...");
return json;
}
}

  输出结果如下:

  

  相信通过上面这个返回结果的分析,我们对各种通知的执行顺序有一个简单了解,后续的一些问题我们有空再议。

  参考文章:

  1、https://blog.csdn.net/u011402896/article/details/80369220

  2、https://zhuanlan.zhihu.com/p/610434341

AOP中的一些重要术语简介的更多相关文章

  1. 【Java面试宝典】说说你对 Spring 的理解,非单例注入的原理?它的生命周期?循环注入的原理, aop 的实现原理,说说 aop 中的几个术语,它们是怎么相互工作的?

    AOP与IOC的概念(即spring的核心) IOC:Spring是开源框架,使用框架可以使我们减少工作量,提高工作效率并且它是分层结构,即相对应的层处理对应的业务逻辑,减少代码的耦合度.而sprin ...

  2. Spring AOP中定义切点(PointCut)和通知(Advice)

    如果你还不熟悉AOP,请先看AOP基本原理,本文的例子也沿用了AOP基本原理中的例子.切点表达式 切点的功能是指出切面的通知应该从哪里织入应用的执行流.切面只能织入公共方法.在Spring AOP中, ...

  3. 正确理解Spring AOP中的Around advice

    Spring AOP中,有Before advice和After advice,这两个advice从字面上就可以很容易理解,但是Around advice就有点麻烦了. 乍一看好像是Before ad ...

  4. Linux中的IO复用接口简介(文件监视?)

    I/O复用是Linux中的I/O模型之一.所谓I/O复用,指的是进程预先告诉内核,使得内核一旦发现进程指定的一个或多个I/O条件就绪,就通知进程进行处理,从而不会在单个I/O上导致阻塞. 在Linux ...

  5. Spring AOP中的动态代理

    0  前言 1  动态代理 1.1 JDK动态代理 1.2 CGLIB动态代理 1.2.1 CGLIB的代理用法 1.2.2 CGLIB的过滤功能 2  Spring AOP中的动态代理机制 2.1  ...

  6. Spring AOP高级——源码实现(2)Spring AOP中通知器(Advisor)与切面(Aspect)

    本文例子完整源码地址:https://github.com/yu-linfeng/BlogRepositories/tree/master/repositories/Spring%20AOP%E9%A ...

  7. 笔记13 AOP中After和AfterReturning的区别

    AOP中 @Before @After @AfterThrowing@AfterReturning的执行顺序 public Object invoke(Object proxy, Method met ...

  8. spring aop中pointcut表达式完整版

    spring aop中pointcut表达式完整版 本文主要介绍spring aop中9种切入点表达式的写法 execute within this target args @target @with ...

  9. Spring AOP中的JDK和CGLib动态代理哪个效率更高?

    一.背景 今天有小伙伴面试的时候被问到:Spring AOP中JDK 和 CGLib动态代理哪个效率更高? 二.基本概念 首先,我们知道Spring AOP的底层实现有两种方式:一种是JDK动态代理, ...

  10. 转:Spring AOP中的动态代理

    原文链接:Spring AOP中的动态代理 0  前言 1  动态代理 1.1 JDK动态代理 1.2 CGLIB动态代理 1.2.1 CGLIB的代理用法 1.2.2 CGLIB的过滤功能 2  S ...

随机推荐

  1. 为什么 Random.Shared 是线程安全的

    在多线程环境中使用 Random 类来生成伪随机数时,很容易出现线程安全问题.例如,当多个线程同时调用 Next 方法时,可能会出现种子被意外修改的情况,导致生成的伪随机数不符合预期. 为了避免这种情 ...

  2. 一文速览 Dubbo 3.0

    本文将带你快速了解 Dubbo3 的设计背景.总体架构与核心特性.与典型用户如阿里巴巴 HSF2 的关系等.也可以通过如下部分了解更多: 小白用户,快速浏览 Dubbo3 核心特性: 下一代通信协议 ...

  3. JavaScript:对象:如何创建对象?

    JS是面向对象的语言,除开基础数据类型,其他所有的数据类型都是对象,包括函数. 如何去理解对象,什么是对象呢? 举个例子,比如我们将日常生活中见到的猫这种动物,抽象成一个类Cat,这里不去谈类是什么概 ...

  4. appium基本使用(Android)

    一.环境搭建 详情可见:https://www.cnblogs.com/lihongtaoya/p/16971096.html 二.元素定位 详情可见:https://www.cnblogs.com/ ...

  5. python网络爬虫数据解析之正则

    本节内容,讲解爬取网络图片,利用正则匹配图片地址 请求网页之后,响应部分内容如下图: 1 时间:2023/1/7 10:42 2 功能描述 3 1.进行指定标签的定位 4 2.标签或者标签对应的属性中 ...

  6. 单向绑定vs双向绑定、单向数据流vs双向数据流

    参考文章:http://www.qb5200.com/article/482839.html 单双向绑定指的是View层跟Model层之间的映射关系 单向绑定vs双向绑定 react采用单向绑定,vu ...

  7. [Unity]Update()与FixedUpdate()

    Update()介绍 首先我们从官方文档的介绍了解: MonoBehaviour.Update() Description Update is called every frame, if the M ...

  8. 双目测距+点云——使用MiddleBurry数据集的图片

    效果 输入: 左图 右图 输出: 视差图 深度图 实现了鼠标点击图片中的位置,显示其深度. 点云 其他例子点云: bicycle motorcycle 使用自己的双目摄像头拍摄的图片: bottle ...

  9. bugku-source-wp详解

    bugku-source-wp详解 F12先看源代码 base64解码 提交flag 发现这个flag是假的 根据提示打开kali直接扫 命令:gobuster dir -u http://114.6 ...

  10. 【学习笔记】XR872 GUI Littlevgl 8.0 移植(文件系统)

    不得不提 在移植的过程中,发现 LVGL 的文件操作接口并不十分完善,在我看来, LVGL 的文件操作接口,应该更多的是为了 LVGL 内部接口方便读取资源文件而设立的,例如读取图像文件,加载字库文件 ...