spring之AOP的概念及简单案例

这篇具有很好参考价值的文章主要介绍了spring之AOP的概念及简单案例。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

AOP概念

AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。

AOP核心概念

Aspect(切面): Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。

Joint point(连接点):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。

Pointcut(切点):表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。

Advice(增强):Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。

Target(目标对象):织入 Advice 的目标对象.。

Weaving(织入):将 Aspect 和其他对象连接起来, 并创建 Adviced object 的过程

举例理解

下面我以一个简单的例子来比喻一下 AOP 中 Aspect, Joint point, Pointcut 与 Advice之间的关系.

让我们来假设一下, 从前有一个叫爪哇的小县城, 在一个月黑风高的晚上, 这个县城中发生了命案. 作案的凶手十分狡猾, 现场没有留下什么有价值的线索. 不过万幸的是, 刚从隔壁回来的老王恰好在这时候无意中发现了凶手行凶的过程, 但是由于天色已晚, 加上凶手蒙着面, 老王并没有看清凶手的面目, 只知道凶手是个男性, 身高约七尺五寸. 爪哇县的县令根据老王的描述, 对守门的士兵下命令说: 凡是发现有身高七尺五寸的男性, 都要抓过来审问. 士兵当然不敢违背县令的命令, 只好把进出城的所有符合条件的人都抓了起来.

来让我们看一下上面的一个小故事和 AOP 到底有什么对应关系.
首先我们知道, 在 Spring AOP 中 Joint point 指代的是所有方法的执行点, 而 point cut 是一个描述信息, 它修饰的是 Joint point, 通过 point cut, 我们就可以确定哪些 Joint point 可以被织入 Advice. 对应到我们在上面举的例子, 我们可以做一个简单的类比, Joint point 就相当于 爪哇的小县城里的百姓,pointcut 就相当于 老王所做的指控, 即凶手是个男性, 身高约七尺五寸, 而 Advice 则是施加在符合老王所描述的嫌疑人的动作: 抓过来审问.
为什么可以这样类比呢?

Joint point : 爪哇的小县城里的百姓: 因为根据定义, Joint point 是所有可能被织入 Advice 的候选的点, 在 Spring AOP中, 则可以认为所有方法执行点都是 Joint point. 而在我们上面的例子中, 命案发生在小县城中, 按理说在此县城中的所有人都有可能是嫌疑人.

Pointcut :男性, 身高约七尺五寸: 我们知道, 所有的方法(joint point) 都可以织入 Advice, 但是我们并不希望在所有方法上都织入 Advice, 而 Pointcut 的作用就是提供一组规则来匹配joinpoint, 给满足规则的 joinpoint 添加 Advice. 同理, 对于县令来说, 他再昏庸, 也知道不能把县城中的所有百姓都抓起来审问, 而是根据凶手是个男性, 身高约七尺五寸, 把符合条件的人抓起来. 在这里 凶手是个男性, 身高约七尺五寸 就是一个修饰谓语, 它限定了凶手的范围, 满足此修饰规则的百姓都是嫌疑人, 都需要抓起来审问.

Advice :抓过来审问, Advice 是一个动作, 即一段 Java 代码, 这段 Java 代码是作用于 point cut 所限定的那些 Joint point 上的. 同理, 对比到我们的例子中, 抓过来审问 这个动作就是对作用于那些满足 男性, 身高约七尺五寸 的爪哇的小县城里的百姓.

Aspect::Aspect 是 point cut 与 Advice 的组合, 因此在这里我们就可以类比: “根据老王的线索, 凡是发现有身高七尺五寸的男性, 都要抓过来审问” 这一整个动作可以被认为是一个 Aspect.

代码案例

我们首先建立配置类Config,在此类开启AspectJ注解@EnableAspectJAutoProxy

注意:在最新版本的Spring框架中,@EnableAspectJAutoProxy注解不是必需的。当你使用<aop:aspectj-autoproxy>配置或者Spring Boot时,它会自动启用AspectJ自动代理。

Spring框架会根据以下条件自动启用AspectJ自动代理:

  1. 在类路径下存在AspectJ织入器(例如,AspectJ的相关依赖已经被引入)。
  2. Spring上下文中存在至少一个@Aspect注解的切面类。

因此,如果你的项目满足这些条件,你无需显式地使用@EnableAspectJAutoProxy注解。Spring框架会自动探测并启用AspectJ自动代理。

Config类:

package com.xsh.springaop;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@ComponentScan
@Configuration
//开启AspectJ注解
@EnableAspectJAutoProxy
public class Config {
}


下列代码是一个简单的AOP切面示例,用于在目标方法执行之前和执行之后打印日志。

  1. @Aspect注解表示这是一个切面类,用于声明切面的功能。
  2. @Component注解表示这个切面类是一个Spring组件,将被Spring容器管理。
  3. @Before("execution(* com.xsh.springaop.MyServer.fun1(..))")注解表示这个方法将在目标方法执行之前执行。它使用了切点表达式来指定切入的连接点。在本例中,切点表达式execution(* com.xsh.springaop.MyServer.fun1(..))表示匹配com.xsh.springaop.MyServer类中的fun1方法,并且方法参数任意。
  4. @After("execution(* com.xsh.springaop.MyServer.fun2(..))")注解表示这个方法将在目标方法执行之后执行。切点表达式与上述相似,匹配com.xsh.springaop.MyServer类中的fun2方法。
  5. beforeMethodExecution()方法是前置通知方法,它在目标方法执行之前被调用,打印了一条日志信息。
  6. afterAdvice()方法是后置通知方法,它在目标方法执行之后被调用,打印了一条日志信息。

通过这种方式,可以在不修改原有业务逻辑的情况下,通过AOP切面对目标方法进行增强操作,例如记录日志、性能监控、事务管理等。在示例中,切面类LoggingAspect将在目标方法执行前后输出日志信息。

LoggingAspect:

package com.xsh.springaop;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;



@Aspect
@Component
public class LoggingAspect {

    @Before("execution(* com.xsh.springaop.MyServer.fun1(..))")
    public void beforeMethodExecution() {
        System.out.println("Before executing method");
    }

    @After("execution(* com.xsh.springaop.MyServer.fun2(..))")
    public void afterAdvice() {
        System.out.println("After executing method");
    }




}


下列代码是有2个方法,分别对应切面类中的所切方法。

MyServer:

package com.xsh.springaop;


import org.springframework.stereotype.Service;

@Service
public class MyServer {


    public void fun1() {
        System.out.println("我是方法1111");
    }

    public void fun2(){
        System.out.println("我是方法2222");
    }

}


下列代码是一个Spring Boot的应用程序启动类。它实现了CommandLineRunner接口,用于在应用程序启动后执行一些初始化任务。

  1. @Component注解表示这个类是一个Spring组件,将被Spring容器管理。
  2. AppRunner类实现了CommandLineRunner接口,它定义了一个run方法,在应用程序启动后会被自动调用。
  3. AppRunner类中,使用@Autowired注解将MyServer类的实例自动注入进来,即将MyServer对象注入到myServer字段中。
  4. run方法中,调用了myServer对象的fun1()fun2()方法,即执行了目标方法。

通过这种方式,当应用程序启动后,AppRunner类的run方法将会被自动调用,从而触发执行MyServer类中的目标方法fun1()fun2()。这样可以方便地测试和验证切面是否生效,是否正确地增强了目标方法的功能。

AppRunner:文章来源地址https://www.toymoban.com/news/detail-451427.html

package com.xsh.springaop;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class AppRunner implements CommandLineRunner {

    @Autowired
    private MyServer myServer;

    @Override
    public void run(String... args) throws Exception {
        myServer.fun1();
        myServer.fun2();
    }
}


到了这里,关于spring之AOP的概念及简单案例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • VRRP的概念及基本配置

    VRRP可以让多个网关能够协同工作但又不会互相冲突,解决了网关单点故障的问题,并且可以实现网关的备份。 VRRP能够在不改变组网的情况下,将多台路由器虚拟成一个虚拟路由器,通过配置虚拟路由器的IP地址为默认网关,实现网关的备份。 协议版本:VRRPv2(常用)和VRR

    2024年02月05日
    浏览(36)
  • 复数的概念及运算(复变函数)

    1. 复数 z= Re(z)+Im(z) i =x+yi (虚数单位 i,   ) 2.复数的代数运算(加减乘除) 3.共轭复数的性质(加减乘除) (1)                     (2)                            4.复数的几何表示 复平面 z=x+iyP(x,y) 复数的模  ,复数的辐角 Argz,辐角主值argz  复数的幅角:以x轴

    2024年02月03日
    浏览(38)
  • git 中分支的概念及使用

    分支模型是 Git 中的 “必杀技特性”, Git 处理分支的方式非常轻量,创建新分支这一操作几乎能在瞬间完成,并且在不同分支之间的切换操作也是一样便捷。 理解和精通这一特性,我们便会意识到 Git 是如此的强大而又独特,并且从此真正改变我们的开发方式。 在版本控制

    2024年01月17日
    浏览(45)
  • 【Linux】进程的概念及操作进程

    背景: 我们通过冯诺依曼体系结构知道,程序需要运行,需要将其从磁盘中传入内存,在传入CPU,由CPU将其运行起来。 了解了这个背景,我们就能对 进程 得出下面的理解: 进程 就是被加载到内存中的程序,或者被运行起来的程序就叫做 进程 。 这也是很多教材上的说法,

    2024年02月03日
    浏览(37)
  • 完全二叉树——堆的概念及实现

    堆(heap):是堆内存的简称,堆是动态分配内存,内存大小不固定,也不会自动释放,堆——数据结构是一种无序的树状结构,同时它还满足key-value键值对的存储方式。 如果有一个关键码的集合K = { , , ,…, },把它的所有元素按完全二叉树的顺序存储方式存储在一个一维

    2024年02月07日
    浏览(37)
  • vuex中mapActions的概念及用法

    先看一下官方文档对mapActions的描述: 简单来说 mapActions 就是 将组件中的函数映射为对应的action 。 一般情况下我们会在组件中使用 this.$store.dispatch() 来触发 action ,想要调用多少个 action 就需要调用多少次 dispatch() ,而使用 mapActions 的话只需要 往 mapActions 中传入与 action 同名

    2024年02月13日
    浏览(40)
  • Spring AOP(AOP概念,组成成分,实现,原理)

    目录 1. 什么是Spring AOP? 2. 为什么要用AOP? 3. AOP该怎么学习? 3.1 AOP的组成 (1)切面(Aspect) (2)连接点(join point) (3)切点(Pointcut) (4)通知(Advice)  4. Spring AOP实现 4.1 添加 AOP 框架支持 ​编辑  4.2 定义切面 4.3 定义切点 4.4 定义通知 4.5 切点表达式说明 AspectJ

    2024年02月13日
    浏览(45)
  • 【数据结构】二叉树的概念及结构

    🚀write in front🚀 📜所属专栏: 初阶数据结构 🛰️博客主页:睿睿的博客主页 🛰️代码仓库:🎉VS2022_C语言仓库 🎡您的点赞、关注、收藏、评论,是对我最大的激励和支持!!! 关注我,关注我,关注我 , 你们将会看到更多的优质内容!! 树是一种 非线性的数据结构

    2023年04月23日
    浏览(44)
  • <数据结构> 链表 - 链表的概念及结构

    概念: 链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的 逻辑顺序 是通过链表中的 指针链接 次序实现的 1、链表由一系列结点(链表中每一个元素称为结点)组成。 2、结点可以在运行时动态(malloc)生成。 3、每个结点包括两个部分:一个是存储数据元素的

    2023年04月09日
    浏览(46)
  • 【RabbitMQ】交换机的概念及使用

            RabbitMQ中,交换机是一个核心概念,主要用来将生产者生产出来的消息,传送到对应的队列中。实际上,生产者生产的消息从不会直接发送到队列,而是发送到交换机。交换机一方面接收来自生产者的消息,另一方面将这些消息推入队列。 四种类型的交换机: 直

    2024年01月25日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包