AOP基础-动态代理

ops/2024/9/25 9:10:11/

文章目录

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/ops/5157.html

相关文章

农业大数据概论-期末复习预测卷

单选 大数据特征 数据量大、多样性、高速性、低价值密度 物联网感知层的关键技术—— RFID技术 电子标签 非接触式的自动识别技术 边缘计算 最近端服务 非常靠近用户 快 定性数据 ① 不精确 ② 描述性 名词解释 农业大数据 农业大数据是融合了农业地域性、季节性、多…

React脚手架的搭建与使用

React脚手架是开发现代Web应用的必备&#xff0c;其充分利用Webpack、Babel、ESlint等工具辅助项目的开发&#xff0c;当然这些工具也无需手动配置即可使用&#xff0c;脚手架的意义更多的是关注的是业务而不是工具的配置&#xff1b;项目的整体技术架构为&#xff1a;react w…

ARM_day8:基于iic总线的通信

一、IIC总线的基本概念&#xff1a; iic总线是一种带应答的同步的、串行、半双工的通信方式&#xff0c;支持一个主机对应多个从机。它有一根SCL&#xff08;时钟线&#xff09;和一根SDA&#xff08;数据线&#xff09;组成&#xff0c;由于只有一根数据线&#xff0c;所以它是…

【C++】vector的模拟实现

在这篇博客中&#xff0c;作者将会带领是简单的实现STL库中的vector。 一.vector的基本结构 vector是一个顺序存储的容器&#xff0c;也可以说是一个数组&#xff0c;那么对于它的结构&#xff0c;我们可以用三个迭代器来组成&#xff0c;如下图&#xff1a; 在vector当中&…

轻松上手MYSQL:MYSQL初识(下)

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《MYSQL入门》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 &#x1f680; 转载自热榜文章&#x1f525;&#xff1a;轻松上手MYSQL&#xff1a;MYSQL初识&a…

设计模式在芯片验证中的应用——策略

1. 策略模式 策略模式是一种行为设计模式&#xff0c; 它能让你定义一系列算法&#xff0c; 并将每种算法分别放入独立的类中&#xff0c; 以使算法的对象能够相互替换。 在RTL设计中可能包含了复杂的多个访问仲裁逻辑&#xff0c;使用了多种算法来确定访问内存优先级顺序&am…

Python爬虫:urllib库的基本使用

文章目录 一、urllib简介二、请求的发送和响应&#xff08;一&#xff09;发送请求&#xff08;二&#xff09;获取相应内容&#xff08;三&#xff09;下载所需文件 三、URL请求对象的定制四、常见请求方式&#xff08;一&#xff09;get请求方式&#xff08;二&#xff09;po…

打开电脑底部导航栏的任务

from pywinauto import Application app Application("uia").connect(path"explorer") app["任务栏"].print_control_identifiers() task app["任务栏"].child_window(title"酷狗音乐", auto_id"D:\soft\kugou\KGMus…