AOP基础-动态代理

news/2024/9/25 9:10:09/

文章目录

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/news/1426673.html

相关文章

[大模型]Qwen-Audio-chat WebDemo 部署

Qwen-Audio-chat WebDemo 部署 Qwen-Audio 介绍 Qwen-Audio 是阿里云研发的大规模音频语言模型&#xff08;Large Audio Language Model&#xff09;。Qwen-Audio 可以以多种音频 (包括说话人语音、自然音、音乐、歌声&#xff09;和文本作为输入&#xff0c;并以文本作为输出…

avail 批量查询空投余额脚本

查询以太坊账户是否有空投的脚本。 首先,定义了一个空的`private_key_lst`列表,用于存储你的私钥。 然后,通过循环遍历`private_key_lst`中的每个私钥,在每次迭代中执行以下操作: 1. 使用私钥生成以太坊账户的地址 `from_address = Account.from_key(private_key).addr…

k8s 架构

1、概述 想要学习k8s的使用还是有必要学习一下k8s的架构。文章这个图是官网上k8s的架构图&#xff0c;这个架构展示了所有k8s的组件。Kubernetes架构可以分为两个主要部分&#xff1a;控制平面&#xff08;Control Plane&#xff09;和数据平面&#xff08;Data Plane&#xf…

【Spring高级】Springboot自动配置类原理

目录 如何引入第三方库第三方库与当前项目Bean重复自定义自动配置类 自动配置类通常位于Spring Boot的自动配置模块中&#xff0c;并且被标记为 Configuration类。这些类使用 Conditional注解来检查某些条件是否满足&#xff0c;如果满足&#xff0c;则创建和配置相关的bean。…

HttpServletRequest/Response

HttpServletRequest 一些常用类的用法 package Demo;import javax.jws.WebService; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import ja…

python中isinstance()作用

Python 中的 isinstance() 函数具有以下作用 &#xff08;类似Java 中的 instanceof &#xff09; 类型检查&#xff1a; isinstance() 用于判断一个对象是否属于特定的类型&#xff08;或类型集合&#xff09;。它接受两个参数&#xff1a;一个是待检测的对象&#xff0c;另一…

web、android和ios共同能够实现滑动及同步测试(实测)

web、android和ios共同能够实现滑动及同步测试&#xff08;实测&#xff09; 1、三者滑动效果 描述&#xff1a;在web页面拼好了之后&#xff0c;使用android和ios进行测试的时候&#xff0c;android轮播图能够实现触摸滑动&#xff0c;但是ios不可以&#xff0c;于是添加一下…

提升性能:QML Canvas 绘图优化技巧

减少绘制操作&#xff1a; 当我们有一个动态更新的图形&#xff0c;例如实时更新的数据可视化图表&#xff0c;可以通过设置一个定时器来控制更新频率&#xff0c;而不是每次数据更新都重新绘制整个图形。 使用硬件加速&#xff1a; 通过将Canvas的renderTarget属性设置为Canv…