三种代理模式
2021/11/1 23:41:03
本文主要是介绍三种代理模式,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1 概念
代理:proxy 结构性模式中的代理模式 要调用目标对象的功能时:不是直接访问目标对象 而是通过代理对象 间接访问目标对象的功能: 对目标对象的功能进行扩展 代理对象:对目标对象的功能进行改进和加功 目标对象:功能被扩展的对象
2 静态代理
要求:
静态代理:为目标对象创建一个代理类:代理类需要关联目标对象 代理类和目标对象实现相同的接口/继承相同的父类 在代理类方法中调用目标对象的方法 在调用之前和之后可以加扩展的代码
目标对象和代理类 必须实现相同的接口或者相同的父类
准备
- 接口
public interface WorkerInterface { void work(); void smoke(String smokeLogo); void sleep(); }
- 目标对象的类
public class Worker implements WorkerInterface { private String wname; public Worker(String wname) { this.wname = wname; } public void work(){ System.out.println("工人:"+wname+",开始工作了!"); } public void smoke(String smokeLogo){ System.out.println("工人:"+wname+",正在吸烟,烟的牌子是"+smokeLogo+"!"); } public void sleep(){ System.out.println("工人:"+wname+",正在休息!"); } @Override public String toString() { return "Worker [wname=" + wname + "]"; } }
- 代理对象的类
package proxy; public class Proxy { public static void main(String[] args) { // 4 创建目标对象 Worker worker = new Worker("张三"); // 5 创建代理对象 并关联目标 WorkerProxy wp = new WorkerProxy(worker); // 6 调用代理对象的方法 wp.sleep(); wp.work(); wp.smoke("中华"); } } // 1 实现相同接口 class WorkerProxy implements WorkerInterface { // 2 关联目标对象 private WorkerInterface worker; public WorkerProxy(WorkerInterface worker) { this.worker = worker; } // 3 在代理对象的方法中 调用目标对象的方法 在调用之前和之后可以加扩展的代码 @Override public void work() { worker.work(); System.out.println(worker + "辛苦了!"); System.out.println("*************************************"); } @Override public void smoke(String smokeLogo) { System.out.println(worker + "吸烟有害健康!"); worker.smoke(smokeLogo); System.out.println("*************************************"); } @Override public void sleep() { System.out.println(worker + "劳逸结合!"); worker.sleep(); System.out.println(worker + "睡觉结束,满血复活!"); System.out.println("*************************************"); } }
总结
优点:可以实现对目标对象功能的扩展 缺点:1 只能代理指定接口的实现类 2 不能对目标对象的特有功能进行扩展
3 动态代理(jdk代理)
概念
*动态代理: * 1.不需要声明定义一个代理类 * 2.代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型) * 3.动态代理也叫做:JDK代理 * *通过java.lang.reflect. Proxy 的newProxyInstance方法在内存中动态生成目标对象的代理对象
*** 动物类 *** package proxy; public class Cat implements Animal{ public void eat(){ System.out.println("猫爱吃鱼!"); } } interface Animal{ void eat(); }
代理对象的工厂类:写法1:普通写法
package proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyF { public static void main(String[] args) { // 创建目标对象 Worker w = new Worker("林风"); // 创建工厂对象 ProxyFactory factroy = new ProxyFactory(w); // 通过工厂对象动态获取一个代理对象 WorkerInterface wi = (WorkerInterface) factroy.getProxy(); wi.sleep(); wi.work(); wi.smoke("芙蓉王"); //创建工厂对象 ProxyFactory factroy2=new ProxyFactory(new Cat()); Animal a=(Animal)factroy2.getProxy(); a.eat(); } } // 1 定义一个代理类工厂对象:实现接口InvocationHandler class ProxyFactory implements InvocationHandler { // 2 定义引用记录目标对象:通过构造方法关联 private Object target; public ProxyFactory(Object target) { this.target = target; } // 3 定义方法: 通过Proxy的newProxyInstance方法动态的在内存中创建目标对象的代理对象 public Object getProxy() { /** * newProxyInstance三个参数 * 1 loader: 用哪个类加载器去加载代理对象 * 2 interfaces:动态代理类需要实现的接口 * 3 h:动态代理方法在执行时,会调用h里面的invoke方法去执行 **/ return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } // 4 实现InvocationHandler的invoke方法:目标对象的每个方法被调用:此invoke方法发都会被调用一次 /** * invoke三个参数 * 1 proxy:就是代理对象,newProxyInstance方法的返回对象 * 2 method:调用的方法 * 3 args:方法中的参数 **/ @Override public Object invoke(Object obj, Method method, Object[] params) throws Throwable { System.out.println(method + ":" + params + ":::方法执行前的扩展"); Object result = null; result = method.invoke(target, params); System.out.println(method + ":" + params + ":::方法执行后的扩展"); System.out.println("*******************************************"); return result; } }
代理对象的工厂类:写法2:匿名内部类来实现
package proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyF { public static void main(String[] args) { // 创建目标对象 Worker w = new Worker("林风"); // 创建工厂对象 ProxyFactory factroy = new ProxyFactory(w); // 通过工厂对象动态获取一个代理对象 WorkerInterface wi = (WorkerInterface) factroy.getProxy(); wi.sleep(); wi.work(); wi.smoke("芙蓉王"); // 创建工厂对象 ProxyFactory factroy2 = new ProxyFactory(new Cat()); Animal a = (Animal) factroy2.getProxy(); a.eat(); } } class ProxyFactory { // 定义引用记录目标对象:通过构造方法关联 private Object target; public ProxyFactory(Object target) { this.target = target; } // 定义方法: 通过Proxy的newProxyInstance方法动态的在内存中创建目标对象的代理对象 public Object getProxy() { /** * newProxyInstance三个参数 * 1 loader: 用哪个类加载器去加载代理对象 * 2 interfaces:动态代理类需要实现的接口 * 3 h:动态代理方法在执行时,会调用h里面的invoke方法去执行 **/ return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { /** * invoke三个参数 * 1 proxy:就是代理对象,newProxyInstance方法的返回对象 * 2 method:调用的方法 * 3 args:方法中的参数 **/ // 实现InvocationHandler的invoke方法:目标对象的每个方法被调用:此invoke方法发都会被调用一次 @Override public Object invoke(Object proxy, Method method, Object[] params) throws Throwable { System.out.println(method + ":" + params + ":::方法执行前的扩展"); Object result = null; result = method.invoke(target, params); System.out.println(method + ":" + params + ":::方法执行后的扩展"); System.out.println("************************************************************"); return result; } }); } }
总结
jdk代理:可以代理任意目标对象:但目标类必须实现接口
4 cglib代理
概念
* CGLIB代理:子类对象 * 在运行时期,在内存中动态的创建一个目标对象类的子类对象 * 被spring框架的aop使用:依赖的jar被融入到了spring-core的jar * 先导入jar: spring-core-3.2.18.RELEASE.jar * 优点:可以为所有对象动态创建代理对象::不需要目标对象实现接口
目标对象类
class Book{ public int add(int a,int b){ System.out.println(a+"+"+b+"="+(a+b)); return a+b; } }
代理工厂类
package proxy; import java.lang.reflect.Method; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; public class ProxyF { public static void main(String[] args) { // 创建目标对象 Book b = new Book(); // 创建工厂对象 ProxyFactory factroy = new ProxyFactory(b); // 通过工厂对象动态获取一个代理对象 Book bproxy = (Book) factroy.getProxy(); // 调用代理对象的方法; System.out.println(bproxy.add(1, 2)); } } // 1 创建代理工厂类 实现接口MethedInterceptor class ProxyFactory implements MethodInterceptor { // 2 关联目标对象 private Object target; public ProxyFactory(Object target) { this.target = target; } // 3 创建方法获取代理对象 public Object getProxy() { // 1 创建工具类 Enhancer eh = new Enhancer(); // 2 指定父类 eh.setSuperclass(target.getClass()); // 3 设置回调函数 eh.setCallback(this); // 4 获取代理对象 return eh.create(); } /** * intercept四个参数 * 1 Object o:代理对象本身 * 2 Method method: 被代理对象的方法 * 3 Object[] objects:函数调用的参数 * 4 MethodProxy methodProxy:方法的代理 **/ // 4 实现intercep方法:目标对象的方法每次被调用 此方法都会被调用 @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { System.out.println("cglib代理:::方法执行前的扩展代码"); Object result = null; result = arg1.invoke(target, arg2); System.out.println("cglib代理:::方法执行后的扩展代码"); return result; } }
总结
cglib代理:不需要目标类 实现接口
这篇关于三种代理模式的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-30java最新版本是什么,有什么特性?-icode9专业技术文章分享
- 2024-11-30[开源]27.8K star!这款 Postman 替代工具太火了!
- 2024-11-30Gzip 压缩入门教程:轻松掌握文件压缩技巧
- 2024-11-29开源工具的魅力:让文档管理更“聪明”
- 2024-11-29Release-it开发入门教程
- 2024-11-29Rollup 插件入门教程:轻松掌握模块打包
- 2024-11-29从零到一,产品经理如何玩转项目管理和团队协作
- 2024-11-29如何通过精益生产管理工具帮助项目团队实现精准进度控制?
- 2024-11-29低代码应用开发课程:新手入门与基础教程
- 2024-11-29入门指南:全栈低代码开发课程