aop介绍

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

 

 

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

 

使用“横切”技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横 切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。Aop 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。正如Avanade公司的高级方案构架师Adam Magee所说,AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离。”

 

实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的 方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。然而殊途同归,实现AOP的技术特性却是相同的,分别为:

 

1、join point(连接点):是程序执行中的一个精确执行点,例如类中的一个方法。它是一个抽象的概念,在实现AOP时,并不需要去定义一个join point。

2、point cut(切入点):本质上是一个捕获连接点的结构。在AOP中,可以定义一个point cut,来捕获相关方法的调用。

3、advice(通知):是point cut的执行代码,是执行“方面”的具体逻辑。

4、aspect(方面):point cut和advice结合起来就是aspect,它类似于OOP中定义的一个类,但它代表的更多是对象间横向的关系。

5、introduce(引入):为对象引入附加的方法或属性,从而达到修改对象结构的目的。有的AOP工具又将其称为mixin。

 

上述的技术特性组成了基本的AOP技术,大多数AOP工具均实现了这些技术。它们也可以是研究AOP技术的基本术语。

 

2.2.2 横切技术

 

“横切”是AOP的专有名词。它是一种蕴含强大力量的相对简单的设计和编程技术,尤其是用于建立松散耦合的、可扩展的企业系统时。横切技术可以使得AOP在一个给定的编程模型中穿越既定的职责部分(比如日志记录和性能优化)的操作。

 

如果不使用横切技术,软件开发是怎样的情形呢?在传统的程序中,由于横切行为的实现是分散的,开发人员很难对这些行为进行逻辑上的实现或更改。例 如,用于日志记录的代码和主要用于其它职责的代码缠绕在一起。根据所解决的问题的复杂程度和作用域的不同,所引起的混乱可大可小。更改一个应用程序的日志 记录策略可能涉及数百次编辑——即使可行,这也是个令人头疼的任务。

 

在AOP中,我们将这些具有公共逻辑的,与其他模块的核心逻辑纠缠在一起的行为称为“横切关注点(Crosscutting Concern)”,因为它跨越了给定编程模型中的典型职责界限。

 

2.2.2.1 横切关注点

 

一个关注点(concern)就是一个特定的目的,一块我们感兴趣的区域,一段我们需要的逻辑行为。从技术的角度来说,一个典型的软件系统包含一些 核心的关注点和系统级的关注点。举个例子来说,一个信用卡处理系统的核心关注点是借贷/存入处理,而系统级的关注点则是日志、事务完整性、授权、安全及性 能问题等,许多关注点——即横切关注点(crosscutting concerns)——会在多个模块中出现。如果使用现有的编程方法,横切关注点会横越多个模块,结果是使系统难以设计、理解、实现和演进。AOP能够比 上述方法更好地分离系统关注点,从而提供模块化的横切关注点。

 

例如一个复杂的系统,它由许多关注点组合实现,如业务逻辑、性能,数据存储、日志和调度信息、授权、安全、线程、错误检查等,还有开发过程中的关注点,如易懂、易维护、易追查、易扩展等,图2.1演示了由不同模块实现的一批关注点组成一个系统。

 

aop2.1.gif

图2.1 把模块作为一批关注点来实现

 

通过对系统需求和实现的识别,我们可以将模块中的这些关注点分为:核心关注点和横切关注点。对于核心关注点而言,通常来说,实现这些关注点的模块是 相互独立的,他们分别完成了系统需要的商业逻辑,这些逻辑与具体的业务需求有关。而对于日志、安全、持久化等关注点而言,他们却是商业逻辑模块所共同需要 的,这些逻辑分布于核心关注点的各处。在AOP中,诸如这些模块,都称为横切关注点。应用AOP的横切技术,关键就是要实现对关注点的识别。

 

如果将整个模块比喻为一个圆柱体,那么关注点识别过程可以用三棱镜法则来形容,穿越三棱镜的光束(指需求),照射到圆柱体各处,获得不同颜色的光束,最后识别出不同的关注点。如图2.2所示:

 

aop2.2.gif

图2.2 关注点识别:三棱镜法则

 

上图识别出来的关注点中,Business Logic属于核心关注点,它会调用到Security,Logging,Persistence等横切关注点。

 

public class BusinessLogic

{

    public void SomeOperation()

    {

       //验证安全性;Securtity关注点;

       //执行前记录日志;Logging关注点;

 

       DoSomething();

 

       //保存逻辑运算后的数据;Persistence关注点;

       //执行结束记录日志;Logging关注点;

    }

}

 

AOP的目的,就是要将诸如Logging之类的横切关注点从BusinessLogic类中分离出来。利用AOP技术,可以对相关的横切关注点封 装,形成单独的“aspect”。这就保证了横切关注点的复用。由于BusinessLogic类中不再包含横切关注点的逻辑代码,为达到调用横切关注点 的目的,可以利用横切技术,截取BusinessLogic类中相关方法的消息,例如SomeOperation()方法,然后将这些“aspect”织 入到该方法中。例如图2.3:

 

aop2.3.gif

图2.3 将横切关注点织入到核心关注点中

 

通过利用AOP技术,改变了整个系统的设计方式。在分析系统需求之初,利用AOP的思想,分离出核心关注点和横切关注点。在实现了诸如日志、事务管 理、权限控制等横切关注点的通用逻辑后,开发人员就可以专注于核心关注点,将精力投入到解决企业的商业逻辑上来。同时,这些封装好了的横切关注点提供的功 能,可以最大限度地复用于商业逻辑的各个部分,既不需要开发人员作特殊的编码,也不会因为修改横切关注点的功能而影响具体的业务功能。

 

为了建立松散耦合的、可扩展的企业系统,AOP应用到的横切技术,通常分为两种类型:动态横切和静态横切。

 

2.2.2.2 动态横切

 

动态横切是通过切入点和连接点在一个方面中创建行为的过程,连接点可以在执行时横向地应用于现有对象。动态横切通常用于帮助向对象层次中的各种方法添加日志记录或身份认证。在很多应用场景中,动态横切技术基本上代表了AOP。

 

动态横切技术的核心主要包括join point(连接点),point cut(切入点),advice(通知)和aspect(方面)。在前面,我已经概要地介绍了这些术语分别代表的含义。接下来,我将以一个具体的实例来进一步阐述它们在AOP动态横切中实现的意义。

 

考虑一个电子商务系统,需要对订单进行添加、删除等管理操作。毫无疑问,在实际的应用场景中,这些行为应与权限管理结合,只有获得授权的用户方能够实施这些行为。采用传统的设计方法,其伪代码如下:

public class OrderManager

{

    private ArrayList m_Orders;

    public OrderManager()

    {

       m_Orders = new ArrayList();

    }

    public void AddOrder(Order order)

    {

        if (permissions.Verify(Permission.ADMIN))

        {

 

            m_Orders.Add(order);

        }

    }

 

    public void RemoveOrder(Order order)

    {

        if (permissions.Verify(Permission.ADMIN))

        {

            m_Orders.Remove(order);

        }

    }

}

 

同样的,在该电子商务系统中,还需要对商品进行管理,它采用了同样的授权机制:

public class ProductManager

{

    private ArrayList m_Products;

    public ProductManager()

    {

        m_Products = new ArrayList();

    }

    public void AddProduct(Product product)

    {

        if (permissions.Verify(Permission.ADMIN))

        {

             m_Products.Add(product);

        }

    }

    public void RemoveProduct(Product product)

    {

        if (permissions.Verify(Permission.ADMIN))

        {

             m_Products.Remove(product);

        }

    }

}

 

如此以来,在整个电子商务系统中,核心业务包括订单管理和商品管理,它们都需要相同的权限管理,如图2.4所示:

 

aop2.4.gif

图2.4 电子商务系统的权限验证实现

 

毫无疑问,利用AOP技术,我们可以分离出系统的核心关注点和横切关注点,从横向的角度,截取业务管理行为的内部消息,以达到织入权限管理逻辑的目 的。当执行AddOrder()等方法时,系统将验证用户的权限,调用横切关注点逻辑,因此该方法即为AOP的join point。对于电子商务系统而言,每个需要权限验证的方法都是一个单独的join point。由于权限验证将在每个方法执行前执行,所以对于这一系列join point,只需要定义一个point cut。当系统执行到join point处时,将根据定义去查找对应的point cut,然后执行这个横切关注点需要实现的逻辑,即advice。而point cut和advice,就组合成了一个权限管理aspect。

 

aop2.5.gif

图2.5 AOP动态横切的技术实现

 

由于aspect是一个封装的对象,我们可以定义这样一个aspect:

private static aspect AuthorizationAspect{……}

 

然后在这个aspect中定义point cut,在point cut中,定义了需要截取上下文消息的方法(注:程序当中应该如何实现呢?),例如:

private pointcut authorizationExecution():

execution(public void OrderManager.AddOrder(Order)) ||

execution(public void OrderManager.DeleteOrder(Order)) ||

execution(public void ProductManager.AddProduct(Product)) ||

execution(public void ProductManager.DeleteProduct(Product));

 

由于权限验证是在订单管理方法执行之前完成,因此在before advice中,定义权限检查:

before(): authorizationExecution()

{

    if !(permissions.Verify(Permission.ADMIN))

    {

        throw new UnauthorizedException();

    }

}

 

通过定义了这样一个完整的aspect,当系统调用OrderManager或ProductManager的相关方法时,就触发了point cut,然后调用相应的advice逻辑。如此以来,OrderManager和ProductManager模块就与权限管理模块完全解除了依赖关系, 同时也消除了传统设计中不可避免的权限判断的重复代码。这对于建立一个松散耦合、可扩展的系统软件是非常有利的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/644693.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录算法训练营第14天 | 二叉树的前序、中序、后序遍历(递归+迭代法)

二叉树的理论基础:(二叉树的种类,存储方式,遍历方式 以及二叉树的定义) https://programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html 二叉树的递归遍历 Leetcode对应的三道习…

我们应该解决哪些计算机网络中的问题,才能实现进程之间基于网络的通信呢?

ps:本文章的图片内容来源都是来自于湖科大教书匠的视频,声明:仅供自己复习,里面加上了自己的理解 这里附上视频链接地址:1.6 计算机网络体系结构(1)—常见的计算机网络体系结构_哔哩哔哩_bilibi…

what is `ContentCachingRequestWrapper` does?

ContentCachingRequestWrapper 是 Spring Framework 中提供的一种包装类,它扩展了 HttpServletRequestWrapper 类,用于缓存请求体的内容。 通常在处理 HTTP 请求时,原生的 HttpServletRequest 对象中的输入流 (getInputStream()) 只能被读取一…

Java玩转《啊哈算法》排序之桶排序

过去心不可得,现在心不可得,未来心不可得 目录在这里 楔子代码地址桶排序代码核心部分优缺点 完整代码演示 升级版核心代码完整代码演示 楔子 大家好!本人最近看了下《啊哈算法》,写的确实不错,生动形象又有趣&#x…

Optional的使用(代替if判断是否为空)

Optional 前言 我的使用 package yimeng;import com.ruoyi.RuoYiApplication; import com.ruoyi.common.core.domain.entity.SysUser; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import java.util.*;SpringBootTes…

OpenCV第 2 课 OpenCV 环境搭建

文章目录 第 2 课 OpenCV 环境搭建1.安装 Numpy2.从 Ubuntu 存储库安装 OpenCV3.验证 OpenCV 安装 第 2 课 OpenCV 环境搭建 1.安装 Numpy 每一张图像都有很多个像素点,这也导致了程序中会涉及大量的数组处理。Numpy 是一个 Python 的拓展库,它对多维数…

mysql临时表简述

概述 业务中经常会对一些表进行聚合组装信息,然后筛选,有些表比较数据量大的时候,会对拖慢查询; 常用的mybatis的分页查询,在查询时会先count一下所有数据,然后再limit分页,即使分页也会有深度…

数据分析-Pandas如何用图把数据展示出来

数据分析-Pandas如何用图把数据展示出来 俗话说,一图胜千语,对人类而言一串数据很难立即洞察出什么,但如果展示图就能一眼看出来门道。数据整理后,如何画图,画出好的图在数据分析中成为关键的一环。 数据表&#xff…

「JavaSE」抽象类接口2

🎇个人主页:Ice_Sugar_7 🎇所属专栏:快来卷Java啦 🎇欢迎点赞收藏加关注哦! 抽象类&接口2 🍉接口间的继承🍉接口的应用🍉总结 🍉接口间的继承 和类的继承…

【每日一题】最长交替子数组

文章目录 Tag题目来源解题思路方法一:双层循环方法二:单层循环 写在最后 Tag 【双层循环】【单层循环】【数组】【2024-01-23】 题目来源 2765. 最长交替子数组 解题思路 两个方法,一个是双层循环,一个是单层循环。 方法一&am…

yarn集群HDFS datanode无法启动问题排查

一、问题场景 hdfs无法访问,通过jps命令查看进程,发现namenode启动成功,但是所有datanode都没有启动,重启集群(start-dfs.sh)后仍然一样 二、原因分析 先看下启动的日志有无报错。打开Hadoop的日志目录 …

线程池中线程数量与队列大小参数的如何设置实践-基于QPS的计算公式

目录 概要 传统方式? 线程池理解? 基于QPS的设置思路? 总结? 概要 线程池是个既靠谱但又陌生的家伙, 像管家一样, 会踏踏实实的把你交代的任务完成, 但很死板, 没有自动安排人的能力, 需要你给它配好人手(线程实例)和承载容量(队列大小), 这些参数关系影响业务服务整体…

rabbitmq基础-java-5、Topic交换机

1、简介 Topic类型的Exchange与Direct相比,都是可以根据RoutingKey把消息路由到不同的队列。 只不过Topic类型Exchange可以让队列在绑定BindingKey 的时候使用通配符! BindingKey 一般都是有一个或多个单词组成,多个单词之间以.分割&#x…

使用Python的pygame库实现迷宫游戏

使用Python的pygame库实现迷宫游戏 关于Python中pygame游戏模块的安装使用可见 https://blog.csdn.net/cnds123/article/details/119514520 先给出效果图: 这个游戏能自动生成迷宫布局。 在这个游戏中,玩家将使用键盘箭头键来移动,并且目标…

深入了解达梦数据库的增删查改操作:从入门到精通

目录 前言: 一.达梦数据库的增删改查 1.创建数据库 2.插入数据 3.查看数据 4.删除数据 5.数据 前言: 在当今数字化的时代,数据库已经成为企业和组织的核心资产,是实现高效数据处理、存储和管理的重要工具。达梦数据库&…

测试用例评审流程

1:评审的过程 A:开始前做好如下准备 1、确定需要评审的原因 2、确定进行评审的时机 3、确定参与评审人员 4、明确评审的内容 5、确定评审结束标准 6、提前至少一天将需要评审的内容以邮件的形式发送给评审会议相关人员。并注明详审时间、地点及偿参与人员等。 7、 在邮件中提醒…

科创板交易规则科普

一、交易时间: 交易日的上午9:30-11:30,下午13:00-15:00,其中9:15-9:25是开盘价公布以及竞价的时间,15:05-15:30是盘后固定价格交易时间。 二、买卖原则: 科创板实行T1交易,按照市场实时价格…

Linux运维实战:CentOS7.6操作系统(Shell脚本基础)

文章目录 第19章 Shell脚本基础19.1 Shell基本语法19.1.1 什么是Shell19.1.2 编程语言分类1.低级语言2.高级语言19.1.3 什么是Shell脚本19.2 Shell变量及运用19.2.1 Shell变量1.变量的设置规则如下2.按照变量的作用可以分成以下4类3.按照变量的作用域可以把变量分成两类:…

音乐证书通过率发布,市场对持有者需求旺盛

音乐证书的考试难度备受关注,通过率终于揭晓。据官方公布的数据,该证书的通过率相对较低,需要考生在音乐技能和表现方面有出色的表现。然而,持有音乐证书的人才在市场上需求旺盛,各种音乐机构和企业对其表现出强烈兴趣…

SpringBoot整合ElasticSearch实现分页查询

本文使用SpringBoot整合ElasticSearch实现分页查询 文章目录 环境准备分页查询方式一方式二 本文小结 环境准备 还是继续使用spring-boot-starter-data-elasticsearch来实现分页查询操作 <!-- spring-boot-starter-data-elasticsearch--> <dependency><groupId&…