1.代理模式是什么:代理模式是Java常见的设计模式之一 。所谓代理模式是指客户端并不直接调用实际的对象,而是通过调用代理,来间接地调用实际的对象 。
2.为什么要使用代理模式:一般是因为客户端不想直接访问实际的对象,或者访问实际的对象存在困难,因此通过一个代理对象来完成间接的访问 。
3.代理模式种类:代理模式主要分为两类,静态代理和动态代理 。静态代理比较简单,是由程序员编写的代理类,并在程序运行前就编译好的,而不是由程序动态产生代理类,这就是所谓的静态 。
一、静态代理又分为聚合式静态代理和继承式静态代理
举个管理员网站记录操作日志的例子:
1.1、聚合式静态代理:
1.1.1、创建一个管理员接口
/** * 场景:管理员网站记录操作日志 * 方式一:聚合式静态代理 * 创建一个管理员接口 */publicinterfaceManager{ voidrecordLog(); }
1.1.2、创建一个管理员类实现管理员接口
/** * 真实管理员类 */publicclassAdminimplementsManager{ @OverridepublicvoidrecordLog(){ System.out.println(\"处理记录日志开始结束之间的业务逻辑 。。。\"); } }
1.1.3、创建一个聚合方式的代理类
/** * 以聚合方式实现的静态代理 */publicclassPolyAdminimplementsManager{ privateAdmin admin; publicPolyAdmin(Admin admin){ this.admin = admin; } @Override publicvoidrecordLog(){ System.out.println(\"Admin 聚合式记录日志开始 。。\"); admin.recordLog(); System.out.println(\"Admin 聚合式记录日志结束 。。\"); } }
1.1.4、测试代码:
/** * 测试聚合式静态代理 */publicclassTestPolyAdmin{publicstaticvoidmain(String[] args){ Manager proxyManager = newPolyAdmin(newAdmin()); proxyManager.recordLog(); } } 输出结果: Admin 聚合式记录日志开始 。。处理记录日志开始结束之间的业务逻辑 。。。Admin 聚合式记录日志结束 。。
1.2、继承式静态代理
1.2.1、创建一个继承式静态代理类:
/** * 继承式静态代理 */publicclassProxyAdminextendsAdmin{ @OverridepublicvoidrecordLog(){ System.out.println(\"Admin 继承式记录日志开始 。。\"); super.recordLog(); System.out.println(\"Admin 继承式记录日志开始 。。\"); } }
1.2.2、测试代码:
/** * 测试继承式静态代理 */publicclassTestProxyAdmin{publicstaticvoidmain(String[] args){ ProxyAdmin proxyAdmin = newProxyAdmin(); proxyAdmin.recordLog(); } }
静态代理模式总结:
优缺点:通过上面的代理代码,我们可以看出代理模式的特点,代理类接受一个Manager接口的对象,任何实现该接口的对象,都可以通过代理类进行代理,增加了通用性 。但是也有缺点,每一个代理类都必须实现一遍委托类(也就是Admin)的接口,如果接口增加方法,则代理类也必须跟着修改 。其次,代理类每一个接口对象对应一个委托对象,如果委托对象非常多,则静态代理类就非常臃肿,难以胜任 。
二、动态代理:动态代理又分为jdk动态代理和cglib动态代理
2.1、jdk动态代理步骤:
- 创建一个实现InvocationHandler接口的类,它必须实现invoke()方法
- 创建被代理的类及接口
- 调用Proxy的静态方法,创建一个代理类
- 通过代理调用方法
importcom.test.Manager; importjava.lang.reflect.InvocationHandler; importjava.lang.reflect.Method; publicclassDynamicProxyimplementsInvocationHandler{ privateObject target; publicDynamicProxy(Object target){ this.target = target; } @OverridepublicObject invoke(Object proxy, Method method, Object[] args)throwsThrowable { System.out.println(\"Admin 动态代理打印日志开始 。。。\"); method.invoke(target,args); System.out.println(\"Admin 动态代理打印日志结束 。。。\"); returnnull; } }
2.1.1、测试代码:
importcom.test.Admin; importcom.test.Manager; importjava.lang.reflect.Proxy; publicclassTestDynamicProxy{publicstaticvoidmain(String[] args){ //需要代理的真实对象Manager manager = newAdmin(); //创建中介类DynamicProxy dynamicProxy = newDynamicProxy(manager); //获取类加载器Class clazz=manager.getClass(); /** *loader 类加载器 *interfaces 实现接口 *h InvocationHandler */Manager proxy = (Manager) Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),dynamicProxy); proxy.recordLog(); } }
2.1.2、jdk动态代理总结:
JDK动态代理有一个强制性要求,就是被代理的类必须实现了某一个接口,或者本身就是接口 。
在测试代码中,Proxy.newProxyInstance()方法需要3个参数:类加载器(要进行代理的类)、被代理类实现的接口,事务处理器 。所以先实例化Admin,实例化InvocationHandler的子类DynamicProxy,将各参数传入Proxy的静态方法newProxyInstance()即可获得manager的代理类,前面的静态代理,代理类是我们编写好的,而动态代理则不需要我们去编写代理类,是在程序中动态生成的 。
推荐阅读
- 如何设置连接wifi优先顺序播放 如何设置连接wifi优先顺序
- 安卓手机门禁卡设置方法 安卓nfc功能怎么开启
- 附:小米12手机返回键设置具体步骤 小米手机怎么设置返回键
- yy语音如何设置按键说话 yy怎么调语音按键
- 怎么不压缩文件夹设置密码 怎样不压缩给文件夹设置密码
- iPhone手机设置DNS步骤 苹果手机如何修改dns的ip
- 设置手机手写笔画粗细方法 手机手写笔画粗细怎么设置
- 微信怎么设置自定义来电铃声 微信怎么设置来电铃声
- iphone手机设置简体手写步骤 苹果手机输入法怎么切换
- 电信卡怎么设置网络快一点 电信卡怎么设置网络最快