Spring (2) AOP

news2025/5/24 17:38:28

目录

1 代理(Proxy)模式

1.1 静态代理

1.2 动态代理

1.2.1 基于接口的动态代理

1.2.2 基于子类的动态代理

2 AOP

2.1 注解开发


1 代理(Proxy)模式

        一种设计模式,它的作用是通过提供一个代理类,让我们在调用目标方法的时候,不再是直接调用,而是通过代理类间接调用

1.1 静态代理

        代理类持有目标对象,并且实现相同的接口,代理类在目标方法调用前后进行额外的操作,代理类和目标对象的关系是在编译期写死的

        静态代理工作原理:

                (1) 定义一个接口(或抽象类),目标对象实现这个接口

                (2) 创建一个代理类,实现目标接口,并持有目标对象

                (3) 代理类重写目标接口方法,在重写方法中调用目标对象同名方法

                (4) 代理类的重写方法在目标对象同名方法前后做额外操作

        示例代码:

// 接口
public interface Travel {
    void vacation();
}

// 目标对象
public class TravelImpl implements Travel{
    @Override
    public void vacation() {
        System.out.println("度假...");
    }
}

// 代理类
public class TravelProxy implements Travel {

    private TravelImpl travel;  //引入目标对象

    public void setTravel(TravelImpl travel) {
        this.travel = travel;
    }

    @Override
    public void vacation() {
        System.out.println("去的车票购买");
        travel.vacation();
        System.out.println("回的车票购买");
    }
}

// 测试
@Test
public void travelTest() throws Exception {
	TravelProxy travel = new TravelProxy();
	travel.setTravel(new TravelImpl());
	travel.vacation();
	// 去的车票购买
	// 度假...
	// 回的车票购买
}

1.2 动态代理

        JAVA动态代理是基于反射实现的,代理类的创建和方法都是在运行期完成的

1.2.1 基于接口的动态代理

        原理: 生成一个方法被增强接口的实现类的代理对象

        涉及的类: java.lang.reflect.Proxy

        涉及的接口: java.lang.reflect.InvocationHandler

        要求: 被代理的类至少实现一个接口

        示例代码:

@Test
public void travelTest() throws Exception {
	// 目标对象
	TravelImpl travelImpl = new TravelImpl();
	/**
	 * newProxyInstance参数说明:
	 *      ClassLoader(类加载器):将被代理类的字节码文件加载到JVM
	 *      Class[](字节码数组):被代理类实现的所有接口的字节码数组
	 *      InvocationHandler(拦截器,被代理类实现的任何"接口方法"都会被拦截)
	 *          proxy:代理对象的引用(一般不用)
	 *          method:被代理对象的方法对象(反射原理)
	 *          args:当前方法所需参数
	 */
	// 生成代理对象
	Travel travelProxy = (Travel) Proxy.newProxyInstance(TravelImpl.class.getClassLoader(), TravelImpl.class.getInterfaces(), new InvocationHandler() {
		@Override
		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			// 获取方法参数
			Object myName = args[0];
			// 获取方法名
			String methodName = method.getName();
			// 执行原始方法(有返回值)
				//参数1:目标对象
				//参数2,方法参数
			System.out.println("去的车票购买");
			Object methodReturn = method.invoke(travelImpl, args);
			System.out.println("回的车票购买");
			// 返回参数
			return methodReturn;
		}
	});
	// 执行代理对象
	travelProxy.vacation();
		//去的车票购买
		//度假...
		//回的车票购买
	travelProxy.study();
		//去的车票购买
		//去求学...
		//回的车票购买
}

1.2.2 基于子类的动态代理

        原理: 生成一个方法被增强该类的子类的代理对象

        引入jar包: cglib

        涉及的类: net.sf.cglib.proxy.Enhancer

        要求: 被代理的类不能是最终类(final,不能被继承)

        示例代码:

@Test
public void staticProxyTest() {
	// 目标对象
	TravelImpl travelImpl = new TravelImpl();
	// 代理对象
	TravelImpl travelProxy = (TravelImpl) Enhancer.create(TravelImpl.class, new MethodInterceptor() {
		@Override
		public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
			System.out.println("去的车票购买");
			Object methodReturn = method.invoke(travelImpl, objects);
			System.out.println("回的车票购买");
			return methodReturn;
		}
	});
	// 执行代理对象
	travelProxy.vacation();
}

2 AOP

        底层核心原理动态代理

        AOP(Aspect Oriented Programming)面向切面编程(使用动态代理技术,在不修改源码的基础上,给程序添加额外的功能)

2.1 注解开发

注解说明
@Aspect标识类为"切面类"
@Pointcut("execution(表达式)")

切入点表达式

例: public * xyz.aboluo.service.impl.*.*(..)

@Before前置通知
@AfterReturning后置通知
@AfterThrowing异常通知
@After最终通知(总会执行)
@Around环绕通知

        (1) 引入依赖

        (2) 切面类

@Component
@Aspect  //标识该类为一个"切面类"
@Order(1)  //针对"多切面",数字越小"越先执行,越后结束"
public class LogAdvice {

    @Pointcut("execution(public * xyz.aboluo.controller.*.*(..))")
    private void pc1() {
    }

    @Pointcut("execution(public * xyz.aboluo.service.impl.*.*(..))")
    private void pc2() {
    }

    @Pointcut("pc1() || pc2()")
    private void pc3() {
    }

    //前置通知
    @Before("pc2()")
    public void beforeAdvice() {
        System.out.println("前置通知,方法前执行");
    }

    //后置通知
    @AfterReturning("pc2()")
    public void afterReturningAdvice() {
        System.out.println("后置通知,方法后执行");
    }

    //异常通知
    @AfterThrowing("pc2()")
    public void afterThrowingAdvice() {
        System.out.println("异常通知,异常时执行");
    }

    //最终通知
    @After("pc2()")
    public void afterAdvice() {
        System.out.println("最终通知,始终执行");
    }

    //环绕通知
    @Around("pc2()")
    public Object aroundAdvice(ProceedingJoinPoint pjp) {
        Object methodReturn = null;
        try {
            System.out.println("前置通知");
            Object target = pjp.getTarget();  //获取被代理对象
            String methodName = pjp.getSignature().getName();  //获取当前方法名
            Object[] args = pjp.getArgs();  //获取当前方法执行所需的参数
            methodReturn = pjp.proceed(args);  //原方法执行
            System.out.println("后置通知");
        } catch (Throwable throwable) {
            System.out.println("异常通知");
        } finally {
            System.out.println("最终通知");
        }
        return methodReturn;
    }
}

        (3) 切面执行顺序

                单切面: @Around --> @Before --> 原始方法 -->@After --> @AfterReturning --> @Throwing

                多切面: 使用@Order(1)注解,数字越"越先执行,越后结束"

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

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

相关文章

可降阶的高阶方程与高阶线性微分方程

目录 可降阶的高阶方程 高阶线性微分方程 齐次方程 非齐次方程 常系数齐次线性微分方程 常系数非齐次线性微分方程 可降阶的高阶方程 我们需要先理解什么是可降解的高阶微分方程。可降解的高阶微分方程是指可以转化为低阶微分方程的方程。 例如,以下是一个二阶…

docker 获取Nvidia 镜像 | cuda |cudnn

本文分享如何使用docker获取Nvidia 镜像,包括cuda10、cuda11等不同版本,cudnn7、cudnn8等,快速搭建深度学习环境。 1、来到docker hub官网,查看有那些Nvidia 镜像 https://hub.docker.com/r/nvidia/cuda/tags?page2&name11.…

高德地图实现-逆地理编码-输入提示-地图标点-实现车库管理

效果图: 我们将学习如何创建一个前端地图应用程序,该应用程序集成了高德地图API,允许用户进行地点搜索、选择和标记,以及执行逆地理编码以获取地址信息。我们将使用Vue.js框架来构建应用程序,并结合高德地图的功能来实…

.NET Upgrade Assistant 升级 .NET MAUI

.NET Upgrade Assistant 是一种可帮助您将应用程序升级到最新的 .NET版本 的工具,并且您可以使用这个工具将您的应用程序从旧平台(例如 Xamarin Forms 和 UWP)迁移到新的平台。此外,这个新版本的工具,可以让您在不更改…

C++ - map 和 set 使用介绍

简介 其实在map 和 set 的底层实现当中有差不多一半的 结构是使用 二叉搜索树来实现,关于二叉搜索树可以看下面这个篇博客:C - 搜索二叉树_chihiro1122的博客-CSDN博客 而 set 是 key 模型,他是直接按照 key 值大小来有规律的在 二叉搜索树当…

pyG教程

introduction中ShapeNet失效问题解决 首先用github中官方最新的shapenet.py中文提示手动下载数据压缩包 # In case shapenet.cs.stanford.edu is offline, try to download the data# from Kaggle instead (requires login):# https://www.kaggle.com/datasets/mitkir/shapene…

提升网速 网卡和驱动

去某宝下单了,是网卡和驱动的问题(某宝说网卡和驱动是一个意思)。以下是操作步骤。 更新驱动程序后从联想官网下载本台电脑对应的驱动 下载可以识别自己主机编号的软件-主机信息识别工具 然后获取编号 然后下载自己的有线网卡

探索装饰艺术的未来,留存传统的精髓

近一个世纪后,装饰艺术终于卷土重来。正如我们在全球新的项目、室内空间和家具中所看到的,那种令我们渴望20世纪初20年代繁荣时期的奢华和魅力。作为装饰艺术建筑和设计的独特身份一直在世界上继续启发着人们,那么从新的设计和现有设计的保留…

5.linux的定时任务调度crontab

一、定时任务调度crontab 1. 定时任务调度crond介绍 ①任务调度:系统在某个时间执行特定的命令和程序 ②任务调度分类:系统工作(病毒扫描),用户工作(备份mysql数据库) 2.定时任务调度crond原…

C++项目实战——基于多设计模式下的同步异步日志系统-⑤-实用工具类设计

文章目录 专栏导读获取系统时间time介绍 getTime函数设计判断文件是否存在stat介绍exists函数设计 获取文件所在路径find_last_of介绍path函数设计 创建文件所在目录mkdir介绍find_first_of介绍函数createDirectory设计 实用工具类整理 专栏导读 🌸作者简介&#xf…

数据的真正价值是数据要素市场化开发

随着人工智能、互联网、物联网、大数据、云计算、区块链等新一代信息化、数字化技术的应用,各行各业都开始了新一轮的产业革命和转型升级。在这个过程中,数据伴随着信息化、数字化的推进越发变得重要,到了2020年直接成为了继土地、劳动力、资…

人工智能AI 全栈体系(三)

第一章 神经网络是如何实现的 一个神经网络用不同的数据做训练,就可以识别不同的东西,那么神经网络究竟是怎么训练的? 三、神经网络是如何训练的? 1. 小朋友如何认识小动物? 小时候,每当看到一个小动物时…

R3LIVE源码解析(10) — R3LIVE中r3live_vio.cpp文件

目录 1 r3live_vio.cpp简介 2 r3live_vio.cpp源码解析 1 r3live_vio.cpp简介 R3LIVE主要的公式推导在VIO上,所以我们来细细的分析这部分的功能。R3LIVE将VIO分成了两步,一是直接通过帧间的光流来追踪地图点,并且通过最小化追踪到的地图点的…

Springboot部署服务器项目上线

第一步,项目打包,有两种方式 第一种、直接在项目根目录打开终端,输入以下语句即可。如下图: mvn clean package -DskipTests 第二种、在右侧点击 Maven选项,选择鼠标左键双击package选项即可。如下图: 两…

《研发效能(DevOps)工程师国家职业技术认证》工信部教考中心认证证书:塑造研发效能的黄金标准丨IDCF

随着科技的飞速发展和市场竞争的日益激烈,高素质的技术管理人才在当今社会中扮演着越来越重要的角色。特别是在信息技术领域,企业对于拥有专业技能和丰富知识的研发效能管理与技术人才的需求愈发旺盛。工业和信息化部教育与考试中心(以下简称…

ueditor百度富文本编辑器粘贴后html丢失class和style样式

问题 项目经理从123在线编辑上排版好的文章,粘贴到项目的编辑器上,样式完全乱了, 排版是这样的: 复制到ueditor后的格式: 这天差地别呀,于是打开代码模式,发现section的属性全没了 但是,sp…

如何规划好自己的工作与学习时间?助你提高办事效率的待办提醒软件

在竞争激烈的职场中,想要脱颖而出、不断提升自我价值,我们必须不断学习。然而,很多上班族都发现工作忙碌,根本没有时间专注于学习。那么,如何规划好工作与学习时间呢?每个人的时间都是有限的,因…

Transformer最直观的解析(译)

在这篇文章中,我们将看看“Transformer”——一个利用注意力机制来提高模型训练速度的模型。Transformer在特定任务中优于谷歌神经机器翻译模型。然而,最大的好处来自于Transformer如何使自己适合并行化。事实上,Google Cloud推荐使用The Tra…

STM32F4的USB Host驱动移植详细步骤及问题解决

文章目录 1、库文件准备2、工程准备3、移植3.1、新建USB相关文件夹3.2、加USB相关代码3.3、添加头文件路径 4、修改相关代码1、修改usbh_usr.c①,usb_conf.h,include部分,②,定义全局宏③,修改usbh_usr.c 2、修改diski…

iis建立站点外网无法访问(防火墙的入站规则和出站)

iis建立站点 外网无法访问 原因: 被防火墙拦截了 处理方式: 打开window防火墙--高级设置--入站 出站就是你访问外网,入站就是外网访问你,用户可以创建入站和出站规则,从而阻挡或者允许特定程序或者端口进行连接; 可以使…