AOP 的详细说明以及基本的使用

2023-05-16

AOP复习

1、AOP简介

AOP(Aspect-OrientedProgramming,面向切面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。

​ OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的复用。

而AOP技术则恰恰相反,它利用一种称为“横切”的技术

​ 剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP代表的是一个横向的关系,如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向方面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。

在这里插入图片描述

2、AOP作用

想象下面的场景,开发中在多个模块间有某段重复的代码,我们通常是怎么处理的?显然,没有人会靠“复制粘贴”吧。在传统的面向过程编程中,我们也会将这段代码,抽象成一个方法,然后在需要的地方分别调用这个方法,这样当这段代码需要修改时,我们只需要改变这个方法就可以了。然而需求总是变化的,有一天,新增了一个需求,需要再多出做修改,我们需要再抽象出一个方法,然后再在需要的地方分别调用这个方法,又或者我们不需要这个方法了,我们还是得删除掉每一处调用该方法的地方。实际上涉及到多个地方具有相同的修改的问题我们都可以通过 AOP 来解决。

3、AOP基本术语

Advice 通知

AOP 的主要作用就是在不侵入原有程序的基础上实现对原有功能的增强, 而增强的方式就是添加通知,就是额外增强一个方法。按照不同的方式通知又分为前置、后置、环绕、异常、带有返回值。

JointPoint 连接点

​ 在上述通知的描述中我们知道,AOP增强就是为原有方法在不侵入的情况下额外添加了一个新的功能,**而新功能和原有方法之间是如何联系到一起的呢?**这里就是引入了连接点的概念了。在AOP中连接点的表现形式为

@Around("execution(* io.renren.test.service.Buy.Play(..))")
// 通过注解来把增强方法和原有方法链接到一起,实现了增强的功能。

Pointcut 切入点

​ 在上述连接点的叙述中,我们知道了AOP 是如何实现都原有功能增强的, 但是通过连接点,增强方法是如何增强原有方法的呢? 这里就需要切入点来实现对原有方法的切入。在AOP的代码中表现形式为

    @Around("execution(* io.renren.test.service.Buy.Play(..))")
    public void Around(ProceedingJoinPoint point) throws Throwable {

        System.out.println("环绕前.....");
        System.out.println(point);
    }

// ProceedingJoinPoint point  过程切入点, 增强方法在此实现对被增强方法的功能增强。通过切入点我们可以得到很多东西, 举例如下

        /**
         * 得到参数
         */
        Object[] args = point.getArgs();
        System.out.println("args=> " + args.toString());
        /**
         * 得到切入点的类型
         */
        String kind = point.getKind();
        System.out.println("kind=> " + kind);
        /**
         *  切入点 得到被增强方法的方法签名
         */
        MethodSignature methodSignature = (MethodSignature) point.getSignature();

        /**
         *  方法签名 到被增强方法的方法
         */
        Method method = methodSignature.getMethod();
        System.out.println("method = > " + method);
        /**
         *  方法 名 到被增强方法的方法 上面的注解
         */
        SysLog sysLog = method.getAnnotation(SysLog.class);
        TestAnnotation test = method.getAnnotation(TestAnnotation.class);
        System.out.println(sysLog.value());
        System.out.println(test.value());
        Signature signature = point.getSignature();
        String name = signature.getName();
        Class declaringType = signature.getDeclaringType();
        int modifiers = signature.getModifiers();
        String declaringTypeName = signature.getDeclaringTypeName();
        System.out.println("name= > " + name + " declaringType => " + declaringType + " modifiers => " + modifiers + " declaringTypeName => " + modifiers);
        System.out.println("signature=> " + signature);
        /**
         *    得到目标
         */
        Object target = point.getTarget();
        System.out.println("target=> " + target);
        System.out.println("环绕后.....");

Aspect 切面

	切面是一个类, **由通知和切点组成, 在AOP代码的实现中为主要部分。**, 而一个通知则包括; 切点、连接点, 所以说, 一个切面就直接包括 AOP中所有东西了。 
/**
 * 切面类
 *
 * @author cyt
 */

@Aspect
@Component
public class Point {

    @Before("execution(* io.renren.test.service.Buy.Play(..))")
    public void Before(ProceedingJoinPoint point) {
        System.out.println("男孩女都有自己喜欢的事情");
    } 
}

4、AOP通知方式

在这里插入图片描述

5、AOP基本使用

目录结构

在这里插入图片描述

主要: 接口、实现类、切面、配置类、测试类

接口和实现类

public interface Buy {
    public void Play(String info);  
}
@Component
public class BoyBuy implements Buy {

    @Override
    public void Play(String info) {
        System.out.println(info);
    }
}

配置类

@ComponentScan(basePackages = {"io.renren.test"})
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ComponentScan(basePackageClasses = {io.renren.test.service.Buy.class})
public class config {

}

测试

public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(config.class);
        BoyBuy buy = context.getBean(BoyBuy.class);
        GirlBuy girl = context.getBean(GirlBuy.class);

        girl.Play("around info  ");
    }
}

在这里插入图片描述

AOP

/**
 * 切面类
 *
 * @author cyt
 */

@Aspect
@Component
public class Point {

     @Before("execution(* io.renren.test.service.Buy.Play(..))")
    public void Before() {
        System.out.println("男孩女都有自己喜欢的事情");
    }
}

在这里插入图片描述

开启环绕通知, 以及打印切入点的信息

  @Around("execution(* io.renren.test.service.Buy.Play(..))")
    public void Around(ProceedingJoinPoint point) throws Throwable {
        System.out.println("环绕前.....");
        System.out.println(point);
        /**
         * 得到参数
         */
        Object[] args = point.getArgs();
        System.out.println("args=> " + args.toString());
        /**
         * 得到切入点的类型
         */
        String kind = point.getKind();
        System.out.println("kind=> " + kind);
        /**
         *  切入点 得到被增强方法的方法签名
         */
        MethodSignature methodSignature = (MethodSignature) point.getSignature();

        /**
         *  方法签名 到被增强方法的方法
         */
        Method method = methodSignature.getMethod();
        System.out.println("method = > " + method);
        /**
         *  方法 名 到被增强方法的方法 上面的注解
         */
        SysLog sysLog = method.getAnnotation(SysLog.class);
        TestAnnotation test = method.getAnnotation(TestAnnotation.class);
        System.out.println(sysLog.value());
        System.out.println(test.value());
        Signature signature = point.getSignature();
        String name = signature.getName();
        Class declaringType = signature.getDeclaringType();
        int modifiers = signature.getModifiers();
        String declaringTypeName = signature.getDeclaringTypeName();
        System.out.println("name= > " + name + " declaringType => " + declaringType + " modifiers => " + modifiers + " declaringTypeName => " + modifiers);
        System.out.println("signature=> " + signature);
        /**
         *    得到目标
         */
        Object target = point.getTarget();
        System.out.println("target=> " + target);
        System.out.println("环绕后.....");
    }

在这里插入图片描述

直接编写连接点, 实现对方法的增强

我们定义了一个切点, 并且把切点配置到通知上面

    /**
     * 定义一个切点
     */
    @Pointcut("execution(* io.renren.test.service.Buy.Play(..))")
    public void AspectJPoint() {
    }

    @Before("AspectJPoint()")
    public void point1() {
        System.out.println("前置通知");
    }

修改切面类中 内容如下。

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

AOP 的详细说明以及基本的使用 的相关文章

  • 如何在从“超级”接口扩展的接口方法上创建方面

    我有一个从基本接口扩展的服务层接口 我想围绕我的服务层接口创建一个切入点 但在基本接口中定义的方法之一上 例如 我的基本接口中有一个名为 save 的方法 我将其放入我的基本接口中 因为我的所有 子 接口都会提供 保存 功能 我想仅在我的
  • $Proxy25 无法转换为我的类 Spring 框架

    我在运行测试时遇到此异常 我正在尝试在 spring 中配置 aop java lang ClassCastException Proxy25 cannot be cast to path UserDao at com playence a
  • AOP::0 处错误,在两种不同方法上应用 aop 的绑定不一致

    我正在尝试在两个不同路径中的两种不同方法上应用 before 方面 class Service1 public Object applyX X x code class Service2 public OtherObject applyY
  • 从 ProceedingJoinPoint 获取 java.lang.reflect.Method?

    问题很简短 有没有办法从aspectj ProceedingJoinPoint 获取Method 对象 目前我正在做 Class parameterTypes new Class joinPoint getArgs length Objec
  • Spring AOP Aspect 无法使用 Mockito 工作

    我有一个 Aspect它编织了我所有控制器操作方法的执行 当我运行系统时它工作得很好 但在单元测试中却不行 我按以下方式使用 Mockito 和 junit RunWith SpringJUnit4ClassRunner class Con
  • 如何使用 SpringBootTest 测试某个方面?

    我使用 Spring Boot 2 1 6 RELEASE 在 Spring 中创建了一个简单的方面 它基本上记录了一个方法所花费的总时间 Aspect Component public class TimeLoggerAspect pri
  • 关于 C# 的 AOP 的建议 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Spring Boot 记录器方面

    当访问特定包的类中的方法时 我在日志方面记录信息时遇到问题 换句话说 不 记录发生 我什至绝望地添加了 System out println 语句 但没有成功 我所有的课程都位于org my package包 即org my package
  • Spring AOP:仅建议使用上下文 Bean?

    我是 Spring AOP 的新手 我尝试使用方面进行日志记录 这是我的配置 方面 Aspect public class LoggerAspect Pointcut execution aop LoggerAspTest private
  • JAX RS 客户端 API 拦截器

    当使用 JAX RS 客户端 API 时 有没有办法通过拦截器将标头添加到请求中 而不是通过显式设置标头 Client client ClientBuilder newClient Response response client targ
  • 预处理 C# - 检测方法

    我需要能够预处理多个 C 文件作为项目的预构建步骤 检测方法的开始 并在方法的开始处 任何现有代码之前 插入生成的代码 但是 我在检测方法的打开时遇到问题 我最初尝试使用正则表达式进行匹配 但最终出现了太多误报 我会使用反射 但 Metho
  • 使用属性调用方法

    我有各种单独的方法 它们都需要执行相同的功能 然后才能继续自己的实现 现在我可以在每个方法中实现这些功能 但我想知道是否有一种方法可以利用attributes去做这个 作为一个非常简单的示例 所有网络调用都必须检查网络连接 public v
  • @AspectJ 类级别注释建议,以注释作为方法参数

    如何获取注释作为定义的建议的参数传递 类级注释 是否可以 来自帖子here https stackoverflow com questions 2011089 aspectj pointcut for all methods of a cl
  • Java Aspect 返回要在方法中使用的值

    我有一个 After运行某些逻辑的java方面 我需要它返回一个结果 一个对象 该结果可以在方面切入点拦截的方法中使用 是否可以 你需要的是 Around它允许您将想要的任何内容返回给建议的对象 Around com xyz myapp U
  • PHP:将类的所有函数包装在子类中

    使用 PHP 库类 我想将其所有公共函数包装在一个子类中 大致如下 class BaseClass function do something some stuff function do something else other stuf
  • Android studio 的aspectj - AJDT 插件在哪里

    如何为 android studio 安装 AJDT 我知道 Eclipse 有一个 但我在 android studio 中找不到任何东西 我想做的是在启动之前对我的每个方法调用进行安全检查 我已经从这个网站尝试过AJDT http ec
  • 面向方面编程(AOP)有哪些缺点?

    面向方面编程有哪些可能的和关键的缺点 例如 新手的神秘调试 可读性影响 我认为最大的问题是没人知道如何定义切面的语义 or 如何非程序地声明连接点 如果您无法独立于要嵌入的上下文来定义某个方面的功能 或者无法以不损害其嵌入的上下文的方式定义
  • Ninject 通过城堡动态代理拦截具有非空构造函数的代理类

    我当前的大部分实现都基于此处提供的信息 Ninject 拦截任何具有特定属性的方法吗 https stackoverflow com questions 6386461 ninject intercept any method with c
  • 围绕建议并继续调用:aspectJ,它是如何工作的?

    我一直在试图弄清楚是什么around advice工作于AspectJ 这并不像下面这样简单before之后advice 有人可以简要介绍一下around建议确实如此 其目的是什么proceed关键词 非常非正式地 一个around adv
  • 带有 Grails 的 AOP

    我想在我的 Grails 项目中创建自定义日志记录注释 My code class MyService AuditLog def method1 println method1 called method2 AuditLog def met

随机推荐

  • CMS 02 前端开发

    1 xff0c vue js 研究 1 1 vue js 介绍 1 vue js 是什么 xff1f vue是一套用于构建用户界面的渐进式框架 vue 被设计为可以自底向上逐层应用 0 渐进式框架 xff1a Progressive 说明v
  • 2.从键盘输入两个正整数,输出这两个整数的商,要求商的小数点后保留5位。例如输入355和113,输出3.14159。

    题目 xff1a 从键盘输入两个正整数 xff0c 输出这两个整数的商 xff0c 要求商的小数点后保留5位 例如输入355和113 xff0c 输出3 14159 程序 xff1a include lt stdio h gt void m
  • 你需要烂熟于心的15个常用JS函数

    今天分享一下我日常工作中常用的15个JS函数 xff0c 希望对于你的日常开发有帮助 xff1a 当前浏览器名称 function getExplorer const ua 61 window navigator userAgent con
  • linux 安装yum 安装php

    安装yum sudo apt get update apt get install lrzsz apt install yum apt get install php7 0 libapache2 mod php7 0
  • linux 命令行美化

    vim etc bashrc 添加下面的代码 PS1 PS1 61 34 033 38 5 87m u tput bold tput sgr0 033 38 5 15m 64 tput sgr0 tput sgr0 033 38 5 119
  • Ubuntu18.0下编译opencv c++并配置clion环境

    预编译阶段 先安装一些依赖 span class token function sudo span span class token function apt get span span class token function insta
  • 谈谈CMDB,ITIL和ITSM概念和简史

    CMDB即配置管理数据库 xff0c 存储与管理企业IT架构中设备的各种配置信息 xff0c 它与所有服务支持和服务交付流程都紧密相联 xff0c 支持这些流程的运转 发挥配置信息的价值 xff0c 同时依赖于相关流程保证数据的准确性 如果
  • Java快排实现

    快速排序 xff1a 基本实现思路 取一个标准位置的数字 用其他位置的数字和标准数进行对比 如果比标准数大 则放到标准数的右边 xff0c 如果比标准数小 则放到标准数的左边 然后使用递归进行持续比对 xff08 注意 递归要有入口 如果当
  • Java 后端项目部署到服务器使用ip访问

    Java 后端项目部署到服务器使用ip访问 一 Maven打包项目 打包成功 xff0c 该路径下会生成一个jar包 二 部署项目 打开服务器 创建文件夹目录用于存放上传的jar包并且进入该文件夹 使用rz命令上传打好的jar包 上传完成
  • 中缀表达式转逆波兰表达式

    中缀表达式转后缀表达式 逆波兰表达式 op 43 icp06421isp01536 思路 假设表达式为string ex 61 34 a 43 b c d 34 将表达式处理为 34 a 43 b c d 34 以 做末尾标识 初始时 栈s
  • vs2022 安装boost库并导入websocketpp示例

    vs2022 安装boost库并导入websocketpp示例 下载并编译boost 因为websocketpp依赖于boost中的asio库 xff0c 所以需要先安装boost库 步骤如下 xff1a 下载源码 boost官网 点击版本
  • P8814 [CSP-J 2022] 解密 题解(二元一次方程)

    CSP J 2022 解密 题目描述 给定一个正整数 k k k xff0c 有 k k k 次询问 xff0c 每次给定三个正整数
  • P1011 [NOIP1998 提高组] 车站 (用方程解斐波那契数列)

    NOIP1998 提高组 车站 题目描述 火车从始发站 xff08 称为第 1 1 1 站 xff09 开出 xff0c 在始发站上车的人数为 a a a xff0c 然
  • P1014 [NOIP1999 普及组] Cantor 表

    NOIP1999 普及组 Cantor 表 题目描述 现代数学的著名证明之一是 Georg Cantor 证明了有理数是可枚举的 他是用下面这一张表来证明这一命题的 xff1a 1 1 1 1 1 1
  • devc++ 输入中文变成问号 和中文乱码问题

    解决方法如下 第一步 打开设置 时间和语言 首选语言 添加中文 xff08 简体 xff09 并设置为首选语言 第二步 打开 管理语言设置 更改系统区域设置 非unicode字符所使用的语言 xff0c 改成中文简体
  • 关于c++动态二维数组

    最近在刷题的时候 想要动态创建一个二维数组 于是写出如下代码 int n a cin gt gt n a 61 new int n n 然后就发现报错了 原来是c 43 43 不支持直接这样创建二维数组 那么怎么创建动态二维数组呢 我暂时知
  • PTA L1-006 最小连续因子

    原题链接 https pintia cn problem sets 994805046380707840 problems 994805138600869888 N有两种情况 1 素数 输出1 和 N 2 合数 因为我们求的是连续因子 不需
  • 什么是数据中台?全面解读数据中台

    伴随着云计算 大数据 人工智能等IT技术迅速发展及与传统行业实现快速融合 xff0c 一场由数字化和智能化转型带来的产业变革正在孕育 随着企业规模不断扩大 业务多元化 中台服务架构的应运而生 中台 早期是由美军的作战体系演化而来的 xff0
  • Running as root without --no-sandbox is not supported

    Running as root without no sandbox is not supported 背景 xff1a Anki安装 在root下启动Anki xff0c 安装时 xff0c 报错 25670 25670 0526 160
  • AOP 的详细说明以及基本的使用

    AOP复习 1 AOP简介 AOP xff08 Aspect OrientedProgramming xff0c 面向切面编程 xff09 xff0c 可以说是OOP xff08 Object Oriented Programing xff