AOP基础-动态代理

embedded/2024/9/25 15:24:58/

文章目录

1.动态代理

1.需求分析

image-20240219204601816

2.动态代理的核心

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

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

3.代码实例
java_17">1.Vehicle.java
java">package com.sxs.spring.proxy;/*** @author 孙显圣* @version 1.0*/
public interface Vehicle {public void run();
}
java_32">2.Car.java
java">package com.sxs.spring.proxy;/*** @author 孙显圣* @version 1.0*/
public class Car implements Vehicle{@Overridepublic void run() {System.out.println("小汽车在路上running。。。。。。");}
}
java_50">3.Ship.java
java">package com.sxs.spring.proxy;/*** @author 孙显圣* @version 1.0*/
public class Ship implements Vehicle {@Overridepublic void run() {System.out.println("大轮船在路上running。。。。。。");}
}
java_68">4.VehicleProxyProvider.java(动态代理模板)
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.测试使用
java">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.代码实例
java_174">1.Cal.java
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);
}
java_192">2.CalImpl.java
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;}
}
java_217">3.VehicleProxyProvider02.java
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.测试
java">    @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

AOP_291">3.AOP问题引出

1.问题提出

image-20240220101224618

2.土方法解决
java_299">修改VehicleProxyProvider02.java
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; //返回动态代理对象}
}
AOP_363">3.极简AOP
AOPjava_365">1.SunAOP.java
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.横切关注点-返回通知}
}
java_391">2.修改VehicleProxyProvider02.java

image-20240220102615893


http://www.ppmy.cn/embedded/4857.html

相关文章

设备连接IoT云平台指南

一、简介 设备与IoT云间的通讯协议包含了MQTT&#xff0c;LwM2M/CoAP&#xff0c;HTTP/HTTP2&#xff0c;Modbus&#xff0c;OPC-UA&#xff0c;OPC-DA。而我们设备端与云端通讯主要用的协议是MQTT。那么设备端与IoT云间是如何创建通信的呢&#xff1f;以连接华为云IoT平台为例…

计算机网络——应用层(4)DHCP和套接字编程

一、动态主机配置协议DHCP 1、关于协议配置&#xff1a; 在协议软件中&#xff0c;给协议参数赋值的动作就叫协议配置一个协议软件在使用前必须已被正确配置&#xff0c;具体的配置信息取决于协议栈连接到互联网的计算机的协议软件需要正确配置的参数包括①IP地址&#xff1b…

【记录一个问题】ubuntu如何显示图形界面

在Ubuntu中&#xff0c;图形界面&#xff08;也称为图形用户界面&#xff0c;GUI&#xff09;是默认启用的。但是&#xff0c;如果你正在使用Ubuntu服务器版或因为某种原因图形界面没有启动&#xff0c;你可以按照以下步骤来启用或恢复图形界面&#xff1a; 检查当前的运行级别…

【python】图像边缘提取效果增强方法-高斯模糊

一、介绍 高斯模糊是一种常用的图像处理技术&#xff0c;用于减少图像中的噪声和细节。它通过对图像中的每个像素点进行加权平均来实现模糊效果。具体而言&#xff0c;高斯模糊使用一个高斯核函数作为权重&#xff0c;对每个像素点周围的邻域进行加权平均。这样可以使得每个像…

如何理解数据库事务

事务的概念起源于数据库系统的设计和实现。在计算机科学领域中&#xff0c;数据库系统被广泛用于存储和管理大量的数据&#xff0c;而事务的概念则是为了解决多用户并发访问数据库时可能出现的一系列问题。 事务的概念最早由 IBM 的科学家 Edgar F. Codd 在 1970 年提出。Codd…

npm run build 自动生成dist.zip

需求场景&#xff1a;每次项目打包都需要手动将dist文件夹&#xff0c;压缩为dist.zip 比较繁琐 功能实现&#xff1a;每次运行npm run build 自动生成 dist.zip 首先下载插件 npm install filemanager-webpack-plugin --save-dev然后在项目根目录找到&#xff1a;vue.config.…

【教程】网络安全(黑客)—0基础学习路线

1.网络安全是什么 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 2.网络安全市场 一、是市场需求量高&#xff1b; 二、则是发展相对成熟…

python 面向对象(封装、继承、多态)

封装 1 封装概述 是指隐藏对象的属性和实现细节&#xff0c;仅对外提供公共访问方式。 2 封装原则 将不需要对外提供的内容都隐藏起来 把属性隐藏&#xff0c;提供公共方法对其访问。 3 封装好处 隐藏实现细节&#xff0c;提供公共的访问方式 提高了代…