AOP基础-动态代理

文章目录

    • 1.动态代理
        • 1.需求分析
        • 2.动态代理的核心
        • 3.代码实例
          • 1.Vehicle.java
          • 2.Car.java
          • 3.Ship.java
          • 4.VehicleProxyProvider.java(动态代理模板)
          • 5.测试使用
    • 2.动态代理深入—横切关注点
        • 1.需求分析
        • 2.四个横切关注点
        • 3.代码实例
          • 1.Cal.java
          • 2.CalImpl.java
          • 3.VehicleProxyProvider02.java
          • 4.测试
    • 3.AOP问题引出
        • 1.问题提出
        • 2.土方法解决
          • 修改VehicleProxyProvider02.java
        • 3.极简AOP
          • 1.SunAOP.java
          • 2.修改VehicleProxyProvider02.java

1.动态代理

1.需求分析

image-20240219204601816

2.动态代理的核心

动态代理主要用于对实现了接口的对象的方法调用前后进行拦截,以执行一些额外的操作,那么就要对这个接口进行动态代理

如安全检查、日志记录、事务处理等,而不需要修改原有类的代码。

3.代码实例
1.Vehicle.java
package com.sxs.spring.proxy;/*** @author 孙显圣* @version 1.0*/
public interface Vehicle {public void run();
}
2.Car.java
package com.sxs.spring.proxy;/*** @author 孙显圣* @version 1.0*/
public class Car implements Vehicle{@Overridepublic void run() {System.out.println("小汽车在路上running。。。。。。");}
}
3.Ship.java
package com.sxs.spring.proxy;/*** @author 孙显圣* @version 1.0*/
public class Ship implements Vehicle {@Overridepublic void run() {System.out.println("大轮船在路上running。。。。。。");}
}
4.VehicleProxyProvider.java(动态代理模板)
package com.sxs.spring.proxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** @author 孙显圣* @version 1.0*/
public class VehicleProxyProvider {//1.一个接口属性,需要使用构造方法传入实现接口的目标对象private Vehicle target_vehicle;public VehicleProxyProvider(Vehicle target_vehicle) {this.target_vehicle = target_vehicle;}//2.编写方法,使用Java的Proxy类动态创建并返回目标对象的代理对象public Vehicle getProxy() {//类加载器和接口信息都使用目标对象反射获取即可ClassLoader classLoader = target_vehicle.getClass().getClassLoader();Class<?>[] interfaces = target_vehicle.getClass().getInterfaces();//4.匿名内部类实现接口,返回对象InvocationHandler invocationHandler = new InvocationHandler() {/*** 这个方法是在通过代理对象调用任何接口方法时被自动调用的。它允许在调用目标对象的方法前后执行自定义逻辑* @param proxy 代理对象* @param method 代理对象要调用的那个方法* @param args 方法的参数* @return 执行invoke方法后的结果* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//方法前的额外操作System.out.println("交通工具开始运行了。。。。。。");//调用方法Object result = method.invoke(target_vehicle, args);//方法后的额外操作System.out.println("交通工具停止运行了。。。。。。");return result;}};/***     public static Object newProxyInstance(*     ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)*     这个方法有三个参数*     ClassLoader loader:用于定义代理类的类加载器(一般使用目标对象的类加载器)*     Class<?>[] interfaces:代理类需要实现的接口列表,这使得代理对象可以被安全地转换为这些接口中的任何一个*     InvocationHandler h:InvocationHandler接口的实现类(使用匿名内部类传入)*///3.使用Proxy.newProxyInstance来返回代理对象Vehicle proxy = (Vehicle) Proxy.newProxyInstance(classLoader,interfaces, invocationHandler);return proxy;}
}
5.测试使用
package com.sxs.spring.proxy;/*** @author 孙显圣* @version 1.0*/
public class Test {@org.junit.jupiter.api.Testpublic void proxy() {Vehicle vehicle = new Ship();//创建代理类的实例,传入实现了接口的目标对象VehicleProxyProvider vehicleProxyProvider = new VehicleProxyProvider(vehicle);//获取代理对象Vehicle proxy = vehicleProxyProvider.getProxy();//使用代理对象执行方法proxy.run();}
}

image-20240219212314525

2.动态代理深入—横切关注点

1.需求分析

image-20240220092730232

2.四个横切关注点
  • 前置通知
  • 返回通知
  • 异常通知
  • 最终通知
3.代码实例
1.Cal.java
package com.sxs.spring.proxy;/*** 计算数量的接口** @author 孙显圣* @version 1.0*/
public interface Cal {public double getSub(double num1, double num2);public double getSum(double num1, double num2);
}
2.CalImpl.java
package com.sxs.spring.proxy;/*** @author 孙显圣* @version 1.0*/
public class CalImpl implements Cal{@Overridepublic double getSub(double num1, double num2) {System.out.println("方法内部打印:" + (num1 - num2));return num1 - num2;}@Overridepublic double getSum(double num1, double num2) {System.out.println("方法内部打印:" + (num1 + num2));return num1 + num2;}
}
3.VehicleProxyProvider02.java
package com.sxs.spring.proxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;/*** @author 孙显圣* @version 1.0*/
public class VehicleProxyProvider02 {//1.传入目标对象private Cal cal;public VehicleProxyProvider02(Cal cal) {this.cal = cal;}//2.编写方法获取动态代理对象public Cal getProxy() {//获取类加载器ClassLoader classLoader = cal.getClass().getClassLoader();//获取接口信息Class<?>[] interfaces = cal.getClass().getInterfaces();//4.匿名内部类实现接口返回对象InvocationHandler invocationHandler = new InvocationHandler() {Object result = null;@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {try {System.out.println("方法执行开始-日志-方法名-" + method.getName()+ "-参数" + Arrays.asList(args)); //1.横切关注点-前置通知result = method.invoke(cal, args);System.out.println("方法执行正常结束-日志-方法名-" + method.getName()+ "-结果-result=" + result); //2.横切关注点-返回通知} catch (Exception e) {System.out.println("方法出现异常-日志-方法名-" + method.getName()+ "-异常类型=" + e.getClass().getName()); //3.横切关注点-异常通知} finally {System.out.println("方法最终结束-日志-方法名-" +method.getName()); //4.横切关注点-最终通知return result; //返回方法的执行结果}}};//3.返回动态代理对象Cal proxy = (Cal) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);return proxy; //返回动态代理对象}
}
4.测试
    @org.junit.jupiter.api.Testpublic void VehicleProxyProvider02Test() {CalImpl cal = new CalImpl();VehicleProxyProvider02 vehicleProxyProvider02 = new VehicleProxyProvider02(cal);Cal proxy = vehicleProxyProvider02.getProxy();proxy.getSub(3,1);System.out.println("===========================================");proxy.getSum(2,4);}

image-20240220100957232

3.AOP问题引出

1.问题提出

image-20240220101224618

2.土方法解决
修改VehicleProxyProvider02.java
package com.sxs.spring.proxy03;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;/*** @author 孙显圣* @version 1.0*/
public class VehicleProxyProvider02 {//1.传入目标对象private Cal cal;public VehicleProxyProvider02(Cal cal) {this.cal = cal;}public void before(Method method, Object[] args) {System.out.println("方法执行开始-日志-方法名-" + method.getName()+ "-参数" + Arrays.asList(args)); //1.横切关注点-前置通知}public void after(Method method, Object result) {System.out.println("方法执行正常结束-日志-方法名-" + method.getName()+ "-结果-result=" + result); //2.横切关注点-返回通知}//2.编写方法获取动态代理对象public Cal getProxy() {//获取类加载器ClassLoader classLoader = cal.getClass().getClassLoader();//获取接口信息Class<?>[] interfaces = cal.getClass().getInterfaces();//4.匿名内部类实现接口返回对象InvocationHandler invocationHandler = new InvocationHandler() {Object result = null;@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {try {before(method, args);result = method.invoke(cal, args);after(method, result);} catch (Exception e) {System.out.println("方法出现异常-日志-方法名-" + method.getName()+ "-异常类型=" + e.getClass().getName()); //3.横切关注点-异常通知} finally {System.out.println("方法最终结束-日志-方法名-" +method.getName()); //4.横切关注点-最终通知return result; //返回方法的执行结果}}};//3.返回动态代理对象Cal proxy = (Cal) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);return proxy; //返回动态代理对象}
}
3.极简AOP
1.SunAOP.java
package com.sxs.spring.proxy03;import java.lang.reflect.Method;
import java.util.Arrays;/*** @author 孙显圣* @version 1.0*/
public class SunAOP {public static void before(Method method, Object[] args) {System.out.println("方法执行开始-日志-方法名-" + method.getName()+ "-参数" + Arrays.asList(args)); //1.横切关注点-前置通知}public static void after(Method method, Object result) {System.out.println("方法执行正常结束-日志-方法名-" + method.getName()+ "-结果-result=" + result); //2.横切关注点-返回通知}
}
2.修改VehicleProxyProvider02.java

image-20240220102615893

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

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

相关文章

0-1背包问题:贪心算法与动态规划的比较

0-1背包问题&#xff1a;贪心算法与动态规划的比较 1. 问题描述2. 贪心算法2.1 贪心策略2.2 伪代码 3. 动态规划3.1 动态规划策略3.2 伪代码 4. C语言实现5. 算法分析6. 结论7. 参考文献 1. 问题描述 0-1背包问题是组合优化中的一个经典问题。假设有一个小偷在抢劫时发现了n个…

CSS继承、层叠和特殊性

继承性 CSS样式的相互传递&#xff0c;也就是说CSS内部标签拥有CSS外部标签的某些样式。我们可以利用CSS的继承性先把网页中具有相同&#xff0c;可继承的样式提取出来&#xff0c;然后进行全局中定义&#xff0c;利用继承属性影响整个页面的样式。 CSS中不可以继承的属性 1…

(C语言)sscanf 与 sprintf详解

目录 1.sprintf函数详解 2. sscanf函数详解 1.sprintf函数详解 头文件&#xff1a;stdio.h 作用&#xff1a;将格式化的数据写入字符串里&#xff0c;也就是将格式化的数据转变为字符串。 演示&#xff1a; #include <stdio.h> struct S {char name[10];int height;…

L1-039 古风排版--Python

中国的古人写文字&#xff0c;是从右向左竖向排版的。本题就请你编写程序&#xff0c;把一段文字按古风排版。 输入格式&#xff1a; 输入在第一行给出一个正整数N&#xff08;<100&#xff09;&#xff0c;是每一列的字符数。第二行给出一个长度不超过1000的非空字符串&a…

【QT进阶】Qt http编程之http与https简单介绍

往期回顾 【QT进阶】Qt Web混合编程之html、 js的简单交互-CSDN博客 【QT进阶】Qt Web混合编程之使用ECharts显示各类折线图等-CSDN博客【QT进阶】Qt Web混合编程之实现ECharts数据交互动态修改-CSDN博客 【QT进阶】Qt http编程之http与https简单介绍 一、什么是http与https …

NX二次开发——矩形排料5(基于最低水平线+遗传算法排料策略实现)

目录 一、概述 二、知识回顾 2.1适应度函数的确定 2.2基因编码 2.3遗传算法复制&#xff08;选择&#xff09; 2.4遗传算法交叉操作 通过交叉操作可以增加种群个体的多样性&#xff0c;既可以产生更多的优秀解。下面通过顺序编码方法进行改进&#xff08;网上有很…

ThreadLocal 实战使用详解

ThreadLocal 知识储备传送门&#xff1a; ThreadLocal 原理及源码详解 ThreadLocal 内存泄漏和常见问题详解 什么是ThreadLocal&#xff1f; ThreadLocal 是一种提供线程本地变量&#xff08;也称为线程局部变量&#xff09;的类&#xff0c;这种变量确保了在不同的线程中访…

vue3:树的默认勾选和全选、取消全选

实现的功能&#xff0c;上面有个选择框&#xff0c;当选中全部时&#xff0c;下方树被全选 代码&#xff1a; <template><div><el-select v-model"selectAll" style"margin-bottom: 10px;" change"handleSelectAllChange">&…

electron打包dist为可执行程序后记【electron-quick-start】

文章目录 目录 文章目录 前言 一、直接看效果 二、实现步骤 1.准备dist文件夹 2.NVM管理node版本 3.准备electron容器并npm run start 4.封装成可执行程序 1.手动下载electron对应版本的zip文件&#xff0c;解决打包缓慢问题 2.安装packager 3.配置打包命令执行内容…

嵌入式linux中利用QT控制蜂鸣器方法

大家好,今天给大家分享一下,如何控制开发板上的蜂鸣器。 第一:开发板原理图 从原理图中可以得出,当引脚输出低电平的时候,对应的蜂鸣器发出响声。 第二:QT代码详细实现 设置一个按钮,点击即可控制BEEP状态发生反转。 #ifndef MAINWINDOW_H #define MAINWINDOW_H#in…

华为鸿蒙生态,威力估计被很多人低估了……

华为鸿蒙生态&#xff0c;威力估计被很多人低估了&#xff01;华为的鸿蒙千帆计划快成了&#xff0c;微信的加盟让计划就基本没问题了。 最近华为公布原生鸿蒙APP进度&#xff0c;在TOP5000应用里面&#xff0c;已经有4000支持了&#xff0c;不是已经开发完成&#xff0c;就是…

c++ 继承和组件的区别

一、什么是继承(Inheritance) 继承是面向对象编程的四大基本特性之一&#xff0c;它允许一个类&#xff08;派生类或子类&#xff09;继承另一个类&#xff08;基类或父类&#xff09;的属性和方法。通过继承&#xff0c;子类可以重用父类的代码&#xff0c;并且可以添加或覆盖…

# C++之STL整理(9)之list用法(创建、赋值、增删查改)详解

C之STL整理&#xff08;9&#xff09;之list用法&#xff08;创建、赋值、增删查改&#xff09;详解 注&#xff1a;整理一些突然学到的C知识&#xff0c;随时mark一下 例如&#xff1a;忘记的关键字用法&#xff0c;新关键字&#xff0c;新数据结构 C 的list用法整理 C之STL整…

win 安装comfigUI 和一些问题

安装内容&#xff0c;参考&#xff08;1&#xff09;有很详细安装方式 windows压缩包安装ComfyUI 在发布页面上&#xff0c;有一个适用于 Windows 的便携式单机版&#xff0c;可以在 Nvidia GPU 上运行&#xff0c;也可以只在 CPU 上运行。 官网下载地址&#xff1a; https:/…

Electron+Vue3整合 - 开发时状态整合

说明 本文介绍一下 Electron Vue3 的整合的基本操作。实现的效果是 &#xff1a; 1、一个正常的Vue3项目&#xff1b; 2、整合加入 Electron 框架 &#xff1a;开发时 Electron 加载的是开发的vue项目&#xff1b;步骤一&#xff1a;创建vue3项目 常规操作&#xff0c;不再赘…

(C语言)fscanf与fprintf函数详解

目录 1 fprintf详解 1.1 向文件流中输入数据 1.2 向标准输入流写数据 2. fscanf函数详解 2.1 从文件中读取格式化数据 2.2 从标准输入流中读取格式化数据 1 fprintf详解 头文件&#xff1a;stdio.h 该函数和printf的参数特别像&#xff0c;只是多了一个参数stream&#…

scss 和css 的区别 scss变量和css变量的区别

scss 和 css 的区别 语法差异&#xff1a; CSS 使用大括号 {} 和分号 ; 来定义样式规则和属性。SCSS 使用了 Sass 的语法&#xff0c;它允许使用类似编程语言的结构&#xff0c;如变量、嵌套规则、混合&#xff08;mixins&#xff09;和继承等。 嵌套规则&#xff1a; 在 SCSS …

删除word中下划线的内容

当试卷的题目直接含答案&#xff0c;不利用我们刷题。这时如果能够把下划线的内容删掉&#xff0c;那么将有利于我们复习。 删除下划线内容的具体做法&#xff1a; ①按ctrl H ②点格式下面的字体 ③选择下划线线型中的_____ ④勾选使用通配符并在查找内容中输入"?&qu…

增强现实(AR)开发框架

增强现实&#xff08;AR&#xff09;开发框架为开发者提供了构建AR应用程序所需的基本工具和功能。它们通常包括3D引擎、场景图、输入系统、音频系统和网络功能。以下是一些流行的AR开发框架。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流…

【C语言】贪吃蛇项目(2)- 实现代码详解

文章目录 前言一、游戏开始界面设计首先 - 打印环境界面其次 - 游戏地图、蛇身及食物的设计1、地图2、蛇身设置及打印3、食物 二、游戏运行环节蛇的上下左右移动等功能蛇的移动 三、结束游戏代码 前言 在笔者的前一篇博客中详细记载了贪吃蛇项目所需的一些必备知识以及我们进行…