代理的概念:为某个对象提供一个代理,以控制对这个对象的访问。 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代。代理类负责请求的预处理、过滤、将请求分派给委托类处理、以及委托类执行完请求后的后续处理。
    抽象对象角色:就是代理类和委托类共同的接口,声明了目标对象和代理对象的共同接口,这样一来在任何可以使用目标对象的地方都可以使用代理对象。
目标对象角色:就是委托类,定义了代理对象所代表的目标对象。
代理对象角色:就是代理类,代理对象内部含有目标对象的引用,从而可以在任何时候操作目标对象;代理对象提供一个与目标对象相同的接口,以便可以在任何时候替代目标对象。代理对象通常在客户端调用传递给目标对象之前或之后,执行某个操作,而不是单纯地将调用传递给目标对象。 静态代理
代理类在程序运行前已经存在的代理方式称为静态代理。 /**
* 定义Demo接口
*/
public interface Demo {
public void save();
} /**
* DemoImpl实现Demo接口并覆写save()方法
* 真实主题,执行具体业务
*/
public class DemoImpl implements Demo {
public void save() {
System.out.println("调用save()方法");
}
} /**
* DemoImplProxy 也实现了Demo接口,并覆写了save()方法,增加了自己的业务
* 代理主题,负责其他业务的处理
*/
public class DemoImplProxy implements Demo {
Demo demoImpl = new DemoImpl(); public void save() {
System.out.println("开始记录日志");
demoImpl.save();
System.out.println("开始结束日志");
}
} 静态代理有一个缺点,每个代理类只能为一个接口服务,这样程序开发中必然会产生许多的代理类。
动态代理
代理类在程序运行前不存在、运行时由程序动态生成的代理方式称为动态代理。
实现动态代理包括三步: (1). 新建代理类和委托类共同的接口以及委托类;
(2). 实现InvocationHandler接口,这是负责连接代理类和委托类的中间类必须实现的接口;
(3). 通过Proxy类新建代理类对象。 第一步:新建代理类和委托类共同的接口以及委托类 public interface Operate { public void operateMethod1(); public void operateMethod2(); public void operateMethod3();
} public class OperateImpl implements Operate { @Override
public void operateMethod1() {
System.out.println("Invoke operateMethod1");
sleep(110);
} @Override
public void operateMethod2() {
System.out.println("Invoke operateMethod2");
sleep(120);
} @Override
public void operateMethod3() {
System.out.println("Invoke operateMethod3");
sleep(130);
} private static void sleep(long millSeconds) {
try {
Thread.sleep(millSeconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} 第二步:实现InvocationHandler接口 java.lang.reflect.InvocationHandler接口的定义如下: /**
*
*Object proxy:被代理的对象
*Method method:要调用的方法
*Object[] args:方法调用时所需要参数
*/
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
} 实现 InvocationHandler 接口 public class TimingInvocationHandler implements InvocationHandler { private Object target;
public TimingInvocationHandler() {}
public TimingInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long start = System.currentTimeMillis();
Object obj = method.invoke(target, args);
System.out.println(method.getName() + " cost time is:" + (System.currentTimeMillis() - start));
return obj;
}
} 第三步:通过Proxy类新建代理类对象 java.lang.reflect.Proxy类的定义如下: /**
*CLassLoader loader:类的加载器
*Class<?> interfaces:得到全部的接口
*InvocationHandler h:得到InvocationHandler接口的子类的实例
*/
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException public class Main {
public static void main(String[] args) {
// create proxy instance
TimingInvocationHandler timingInvocationHandler = new TimingInvocationHandler(new OperateImpl());
Operate operate = (Operate)(Proxy.newProxyInstance(Operate.class.getClassLoader(), new Class[] {Operate.class},
timingInvocationHandler)); // call method of proxy instance
operate.operateMethod1();
System.out.println();
operate.operateMethod2();
System.out.println();
operate.operateMethod3();
}
} 下面总结一下动态代理对象创建过程 // InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
// 其内部通常包含指向委托类实例的引用,用于真正执行分派转发过来的方法调用
InvocationHandler handler = new InvocationHandlerImpl(..); // 通过 Proxy 为包括 Interface 接口在内的一组接口动态创建代理类的类对象
Class clazz = Proxy.getProxyClass(classLoader, new Class[] { Interface.class, ... }); // 通过反射从生成的类对象获得构造函数对象
Constructor constructor = clazz.getConstructor(new Class[] { InvocationHandler.class }); // 通过构造函数对象创建动态代理类实例
Interface Proxy = (Interface)constructor.newInstance(new Object[] { handler }); 从上面可以看到,实际使用过程更加简单,因为 Proxy 的静态方法 newProxyInstance 已经为我们封装了步骤 2 到步骤 4 的过程,所以简化后的过程如下 // InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
InvocationHandler handler = new InvocationHandlerImpl(..); // 通过 Proxy 直接创建动态代理类实例
Interface proxy = (Interface)Proxy.newProxyInstance( classLoader,
new Class[] { Interface.class },
handler ); 参考文章: Java 动态代理机制分析 公共技术点之 Java 动态代理 代理模式和android插件化 Android设计模式源码解析之Proxy模式

Android中的代理模式的更多相关文章

  1. Objective-C中的委托(代理)模式

    我个人更喜欢把委托(Delegate)模式称为代理(Proxy)模式.还是那句话,第一次接触代理模式是在Java中接触的,在Java中实现代理模式和接口是少不了的.当时学习Spring的时候用到了接口 ...

  2. OC中的代理模式

    OC中的代理模式,关于代理模式,如果还有同学不太清楚的话,就自己去补充知识了,这里就不做介绍了,这里只介绍OC中是如何实现代理模式的.这里举一个简单的例子:小孩类,护士类,保姆类,其中小孩类有两个方法 ...

  3. (转)轻松学,Java 中的代理模式及动态代理

    背景:讲到反射机制,肯定会想到动态代理. 轻松学,Java 中的代理模式及动态代理 代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强.值得注意的是,代理类和被代理类应该 ...

  4. 简介Python设计模式中的代理模式与模板方法模式编程

    简介Python设计模式中的代理模式与模板方法模式编程 这篇文章主要介绍了Python设计模式中的代理模式与模板方法模式编程,文中举了两个简单的代码片段来说明,需要的朋友可以参考下 代理模式 Prox ...

  5. 「补课」进行时:设计模式(5)——从 LOL 中学习代理模式

    1. 前文汇总 「补课」进行时:设计模式系列 2. 从 LOL 中学习代理模式 我是一个很喜欢玩游戏的人,虽然平时玩游戏的时间并不多,但我也是一个忠实的 LOL 的爱好者,就是段位有点惨不忍睹,常年倔 ...

  6. 理解Android系统的进程间通信原理(一)----RPC中的代理模式

    Android系统中的进程间通信是通过一个轻量级的RPC(Remote Procedure Call远程进程调用)和AIDL(Android Interface Definination Langua ...

  7. Java中的代理模式

    代理模式在Java Web的框架中经常使用到.比如说在对数据库的访问中,核心功能是对数据库的增删改查,而连接数据库.处理事务等功能我们在开发中也要考虑到.所以我们将数据库的CRUD抽象到接口中,然后实 ...

  8. Android中的启动模式(下)

    在这篇文章中,我会继续跟大家分享有关于Android中启动模式的相关知识.当然,如果对这个启动模式还不完全了解或者没有听过的话,可以先看看我之前写的有关于这个知识点的入门篇Android的启动模式(上 ...

  9. 说说Java中的代理模式

    今天看到传智播客李勇老师的JDBC系列的第36节——通过代理模式来保持用户关闭连接的习惯.讲的我彻底蒙蔽了,由于第一次接触代理模式,感到理解很难,在博客园找到一篇文章,先记录如下: 引用自java设计 ...

随机推荐

  1. Code Forces 149DColoring Brackets(区间DP)

     Coloring Brackets time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  2. HDU_5521_Meeting

    Meeting Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total ...

  3. 对10进制16位长的主键的缩短处理 NULL

    # 对问题表去除旧有主键,新建自增主键:ALTER TABLE `question`CHANGE COLUMN `id` `id16` bigint(20) NULL COMMENT 'id_to_d ...

  4. Ubuntu安装pycurl

    转自:https://blog.csdn.net/qq_23729557/article/details/78836547 在Ubuntu 16.04上安装pycurl时大致会遇到一下两个问题: 在使 ...

  5. Linux下编译安装PHP扩展memcached

    [安装 libevent] $ tar zxvf libevent-2.0.20-stable.tar.gz $ cd libevent-2.0.20-stable/$ ./configure --p ...

  6. Java多线程(三)

    本文主要接着前面多线程的两篇文章总结Java多线程中的线程安全问题. 一.一个典型的Java线程安全例子 1 public class ThreadTest { 2 3 public static v ...

  7. cocos代码研究(12)UI之Widget学习笔记

    理论基础 Widget类,所有UI控件的基类. 这类继承自ProtectedNode和LayoutParameterProtocol. 如果你想实现自己的UI控件,你应该继承这个类. 被 VideoP ...

  8. Could not load file or assembly 'Microsoft.Practices.EnterpriseLibrary.Common, Version=5.0.414.0, ...

    使用oracle数据库一个多月依赖这问题一直都得不到解决,最近任务不是很忙了,所以决定把这问题解决掉.写一篇文章做记录. 以上错误主要是net程序oracle数据库使用了Microsoft Enter ...

  9. Java之Integer源码

    1.为什么Java中1000==1000为false而100==100为true? 这是一个挺有意思的讨论话题. 如果你运行下面的代码 Integer a = 1000, b = 1000; Syst ...

  10. python中的TCP及UDP

    python中是通过套接字即socket来实现UDP及TCP通信的.有两种套接字面向连接的及无连接的,也就是TCP套接字及UDP套接字. TCP通信模型 创建TCP服务器 伪代码: ss = sock ...