代理模式的理解(以静态代理为例)

代理模式可以看作对目标类的包装,1. 目标实例作为代理实例的属性(即绑定),2. 代理类的接口和目标类的接口是对接的(比如目标类实现了代理类的接口),3. 其次代理类可以实现额外的功能。
- 案例:创建多线程中,Thread类就是代理类,它不但使用了执行了当前实例的功能,而且做了线程管理等扩展。作为开发者,我们不需要操心如何管理线程等细节,就可以实现多线程执行。
静态代理的缺点:代理类和被代理类都在编译期间被确定下来,不利于程序的进一步扩展,比如被代理类越多就需要越多的代理类。
动态代理特点:在运行期才确定代理类和被代理类,并且一个代理类就可以完成全部的代理工作。(通过反射实现,解决静态代理的缺点)
下图中。在编译阶段,通用代码的逻辑实现是确定的,而部分逻辑实现是不确定的,当运行阶段时,我们才确定逻辑实现。

代码
需求:在排序任务中,具体使用什么排序方法是随机的,但是其他代码部分是通用的。
下面代码放置于包 com.xj.java下,执行SortTask.java文件。 SortTask.java是使用动态代理实现的任务逻辑代码 , Sort.java是具体排序方法的实现,Util.java是通用代码的实现。
整体逻辑是,我希望在排序任务的处理中,通用代码是固定的,但是排序的核心算法是动态选择的。 核心代码块即class ProxyFactory和class MyInvocationHandler implements InvocationHandler,因为它们解决了两个实现动态代理的关键问题(见下SortTask.java)。
Sort.javaSortTask.javaUtil.java
SortTask.java
要想实现动态代理,注意下面解决的问题?
问题一:如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象。class ProxyFactory
问题二:当通过代理类的对象调用方法a时,如何动态的去调用被代理类中的同名方法a。class MyInvocationHandler implements InvocationHandler
package com.xj.java;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.util.Random;/*** @author jia* @create 2021-12-22 2:49 下午** 要想实现动态代理,需要解决的问题?* 问题一:如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象。* 问题二:当通过代理类的对象调用方法a时,如何动态的去调用被代理类中的同名方法a。*/public class SortTask {public static void main(String[] args) {// 随机选择排序的方法Sort proxyInstance = null;int t = new Random().nextInt(2);switch (t) {case 0:proxyInstance = (Sort)ProxyFactory.getProxyInstance(new QuickSort());case 1:proxyInstance = (Sort)ProxyFactory.getProxyInstance(new MergeSort());}// 执行排序任务proxyInstance.sort();}}class ProxyFactory{//调用此方法,返回一个代理类的对象。解决问题一public static Object getProxyInstance(Object obj){// obj:被代理类的对象MyInvocationHandler handler = new MyInvocationHandler();handler.bind(obj);// 当通过代理类对象调用方法时,会自动的调用被代理类中同名的方法return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);}}class MyInvocationHandler implements InvocationHandler {private Object obj;public void bind(Object obj){this.obj = obj;} // 赋值被代理类的实例// 当执行"代理类的对象.方法a"时,就会自动的调用如下的方法:invoke() 解决问题二// 本质是通过反射来调用被代理类的方法@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Util util = new Util(); // 在AOP设计模式中,可以额外执行一些通用方法util.method1();// 核心处理过程Object returnValue = method.invoke(obj,args);util.method2();//返回invoke()的返回值。return returnValue;}}
这是排序任务的通用方法1 执行归并排序 这是排序任务的通用方法2
Sort.java
package com.xj.java;/*** @author jia* @create 2021-12-22 3:09 下午*/public interface Sort {public void sort();}class QuickSort implements Sort {@Overridepublic void sort(){System.out.println("执行快速排序");}}class MergeSort implements Sort{@Overridepublic void sort(){System.out.println("执行归并排序");}}
Util.java
package com.xj.java;/*** @author jia* @create 2021-12-22 2:51 下午*/public class Util {public void method1(){System.out.println("这是排序任务的通用方法1");}public void method2(){System.out.println("这是排序任务的通用方法2");}}
