说起代理模式,我们想到的就是Spring AOP的实现,主要场景有记录日志,事务管理等。
而Spring AOP实现代理模式有两种方式,一种是基于接口的JDK动态代理,一种是基于类的CGlib,今天我们要说的就是基于接口的JDK动态代理。主要从两个方面介绍,一个是使用,一个是原理。
JDK的动态代理如何使用呢?比如我们有这样的需求,要统计Service层的各个方法的开始时间,结束时间,及每个方法的运行时间。如果用常规做法呢就是在每个方法里加startTime,endTime然后相减,这太累了,那方法多得去了。下面来看用JDK的动态代理如何实现这个功能:
以UserService举例吧:
接口:
public interface UserService { void addUser(); void editUser(); }实现类:
public class UserServiceImpl implements UserService { @Override public void addUser() { System.out.println("---------- addUser success"); } @Override public void editUser() { System.out.println("---------- editUser success"); } }生成代理对象的Handler,要实现InvocationHandler接口并实现invoke方法:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class LoggerProxyHandler implements InvocationHandler { private Object object; //被代理对象 public LoggerProxyHandler(Object object) { this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long start = System.currentTimeMillis(); System.out.println("++++++++++++ startTime: "+start); Object obj = method.invoke(object, args); long end = System.currentTimeMillis(); System.out.println("++++++++++++ endTime: "+end+", spendTime: "+(end-start)+"ms"); return obj; } }调用(测试)类:
import java.lang.reflect.Proxy; public class ProxyTest { public static void main(String[] args) { //被代理对象 UserService userService = new UserServiceImpl(); //生成代理对象的Handler LoggerProxyHandler handler = new LoggerProxyHandler(userService); //生成代理对象 UserService userServiceProxy = (UserService)Proxy.newProxyInstance(ProxyTest.class.getClassLoader(), new Class[]{UserService.class}, handler); userServiceProxy.addUser(); System.out.println(); userServiceProxy.editUser(); } }运行结果为:
++++++++++++ startTime: 1521983621301 ---------- addUser success ++++++++++++ endTime: 1521983621302, spendTime: 1ms ++++++++++++ startTime: 1521983621302 ---------- editUser success ++++++++++++ endTime: 1521983621302, spendTime: 0ms
以上就是用JDK动态代理实现的记录日志,主要实现InvocationHandler接口并实现invoke方法,还有一点就是JDK动态代理只能针对接口进行代理,不能对类,要对类进行代理可以使用CGlib代理。
首先当然就是要进入Proxy的newProxyInstance方法,这里是产生代理的入口,源码如下。
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { if (h == null) { throw new NullPointerException(); } /* * Look up or generate the designated proxy class. */ Class cl = getProxyClass(loader, interfaces); /* * Invoke its constructor with the designated invocation handler. */ try { Constructor cons = cl.getConstructor(constructorParams); return (Object) cons.newInstance(new Object[] { h }); } catch (NoSuchMethodException e) { throw new InternalError(e.toString()); } catch (IllegalAccessException e) { throw new InternalError(e.toString()); } catch (InstantiationException e) { throw new InternalError(e.toString()); } catch (InvocationTargetException e) { throw new InternalError(e.toString()); } }这个方法其实很简单,首先获取了代理类的运行时Class引用,然后调用了这个Class中的构造方法,这个构造方法只有一个参数,正是InvocationHandler接口,由此产生了一个代理类的实例。那么关键的地方就在于如何获取的代理类运行时的class信息的呢?我们进入getProxyClass方法看一下。为了方便起见,我直接加注释,这个方法需要解释的地方比较多。
public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) throws IllegalArgumentException { //如果传入的接口长度大于65535就抛出异常,我去你妹。。。 if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } Class proxyClass = null; /* collect interface names to use as key for proxy class cache */ String[] interfaceNames = new String[interfaces.length]; Set interfaceSet = new HashSet(); // for detecting duplicates for (int i = 0; i < interfaces.length; i++) { /* * Verify that the class loader resolves the name of this interface * to the same Class object. */ String interfaceName = interfaces[i].getName(); Class interfaceClass = null; try { //加载每一个接口的运行时Class信息 interfaceClass = Class.forName(interfaceName, false, loader); } catch (ClassNotFoundException e) { } //如果采用你传入的类加载器载入的Class和你传入的Class不相等则抛出异常 if (interfaceClass != interfaces[i]) { throw new IllegalArgumentException(interfaces[i] + " is not visible from class loader"); } //如果你传入的不是接口抛出异常 /* * Verify that the Class object actually represents an interface. */ if (!interfaceClass.isInterface()) { throw new IllegalArgumentException(interfaceClass.getName() + " is not an interface"); } //如果你传入的接口重复抛异常 /* * Verify that this interface is not a duplicate. */ if (interfaceSet.contains(interfaceClass)) { throw new IllegalArgumentException("repeated interface: " + interfaceClass.getName()); } interfaceSet.add(interfaceClass); interfaceNames[i] = interfaceName; } /* * Using string representations of the proxy interfaces as keys in the * proxy class cache (instead of their Class objects) is sufficient * because we require the proxy interfaces to be resolvable by name * through the supplied class loader, and it has the advantage that * using a string representation of a class makes for an implicit weak * reference to the class. */ Object key = Arrays.asList(interfaceNames); /* * Find or create the proxy class cache for the class loader. */ Map cache; synchronized (loaderToCache) { //这个是为了存储每一个类加载器所载入过的代理接口的代理类 cache = (Map) loaderToCache.get(loader); if (cache == null) { cache = new HashMap(); loaderToCache.put(loader, cache); } /* * This mapping will remain valid for the duration of this method, * without further synchronization, because the mapping will only be * removed if the class loader becomes unreachable. */ } /* * Look up the list of interfaces in the proxy class cache using the * key. This lookup will result in one of three possible kinds of * values: null, if there is currently no proxy class for the list of * interfaces in the class loader, the pendingGenerationMarker object, * if a proxy class for the list of interfaces is currently being * generated, or a weak reference to a Class object, if a proxy class * for the list of interfaces has already been generated. */ synchronized (cache) { /* * Note that we need not worry about reaping the cache for entries * with cleared weak references because if a proxy class has been * garbage collected, its class loader will have been garbage * collected as well, so the entire cache will be reaped from the * loaderToCache map. */ do { //检查是否有生成好的代理 Object value = cache.get(key); if (value instanceof Reference) { proxyClass = (Class) ((Reference) value).get(); } //有的话直接返回 if (proxyClass != null) { // proxy class already generated: return it return proxyClass; //否则看一下这个代理类是不是正在构造中,是的话就在cache对象上等待 } else if (value == pendingGenerationMarker) { // proxy class being generated: wait for it try { cache.wait(); } catch (InterruptedException e) { /* * The class generation that we are waiting for should * take a small, bounded time, so we can safely ignore * thread interrupts here. */ } continue; //如果没有现成的,也没有创造中的,那就开始创造代理类 } else { /* * No proxy class for this list of interfaces has been * generated or is being generated, so we will go and * generate it now. Mark it as pending generation. */ //将当前代理类置为正在构造中,并直接退出循环 cache.put(key, pendingGenerationMarker); break; } } while (true); } try { String proxyPkg = null; // package to define proxy class in //这一段是看你传入的接口中有没有不是public的接口,如果有,这些接口必须全部在一个包里定义的,否则抛异常 /* * Record the package of a non-public proxy interface so that the * proxy class will be defined in the same package. Verify that all * non-public proxy interfaces are in the same package. */ for (int i = 0; i < interfaces.length; i++) { int flags = interfaces[i].getModifiers(); if (!Modifier.isPublic(flags)) { String name = interfaces[i].getName(); int n = name.lastIndexOf('.'); String pkg = ((n == -1) ? "" : name.substring(0, n + 1)); if (proxyPkg == null) { proxyPkg = pkg; } else if (!pkg.equals(proxyPkg)) { throw new IllegalArgumentException( "non-public interfaces from different packages"); } } } if (proxyPkg == null) { // if no non-public proxy interfaces, proxyPkg = ""; // use the unnamed package } { /* * Choose a name for the proxy class to generate. */ long num; synchronized (nextUniqueNumberLock) { num = nextUniqueNumber++; } //生成一个随机代理类名 String proxyName = proxyPkg + proxyClassNamePrefix + num; /* * Verify that the class loader hasn't already defined a class * with the chosen name. */ //这一句就是重中之重了,生成代理类的class文件,这就是JDK动态代理的原理了,通过动态生成class文件来产生的代理类 //这个generateProxyClass方法下面会着重介绍 /* * Generate the specified proxy class. */ byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces); try { //得到class文件二进制流后,直接载入代理类 proxyClass = defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); } catch (ClassFormatError e) { /* * A ClassFormatError here means that (barring bugs in the * proxy class generation code) there was some other invalid * aspect of the arguments supplied to the proxy class * creation (such as virtual machine limitations exceeded). */ throw new IllegalArgumentException(e.toString()); } } //proxyClasses这个Map是为了来判断是不是代理的Class // add to set of all generated proxy classes, for isProxyClass proxyClasses.put(proxyClass, null); } finally { /* * We must clean up the "pending generation" state of the proxy * class cache entry somehow. If a proxy class was successfully * generated, store it in the cache (with a weak reference); * otherwise, remove the reserved entry. In all cases, notify all * waiters on reserved entries in this cache. */ synchronized (cache) { if (proxyClass != null) { //最终将生成的代理用弱引用包装起来放到cache当中 cache.put(key, new WeakReference(proxyClass)); } else { //如果代理类是空则移除代理的接口所代表的key值 cache.remove(key); } //通知正在等待在cache对象上的线程,告诉他们可以继续了,代理Class加载完毕了 cache.notifyAll(); } } return proxyClass; }上面基本上已经解释的很清楚了,下面就是去看一下byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces)这句话是如何处理的,也就是如何得到的代理类的class文件的,我们进去源码看一下,我依然会加上注释。
public static byte[] generateProxyClass(String paramString, Class[] paramArrayOfClass) { //新建一个ProxyGenerator实例,传入类名和接口数组 ProxyGenerator localProxyGenerator = new ProxyGenerator(paramString, paramArrayOfClass); //这个才是真正生成class文件的地方 final byte[] arrayOfByte = localProxyGenerator.generateClassFile(); //看保存生成文件的标志是否为真,如果是就将class文件生成到本地,生成时要检查权限 if (saveGeneratedFiles) { AccessController.doPrivileged(new PrivilegedAction() { public Object run() { try { FileOutputStream localFileOutputStream = new FileOutputStream( ProxyGenerator.dotToSlash(this.val$name) + ".class"); localFileOutputStream.write(arrayOfByte); localFileOutputStream.close(); return null; } catch (IOException localIOException) { throw new InternalError( "I/O exception saving generated file: " + localIOException); } } }); } return arrayOfByte; }我们继续跟踪到localProxyGenerator.generateClassFile()这一句当中,依然会加上注释。
private byte[] generateClassFile() { //addProxyMethod方法,就是将方法都加入到一个列表中,并与对应的class对应起来 //这里给Object对应了三个方法hashCode,toString和equals addProxyMethod(hashCodeMethod, Object.class); addProxyMethod(equalsMethod, Object.class); addProxyMethod(toStringMethod, Object.class); //同样将接口与接口下的方法对应起来 for (int i = 0; i < this.interfaces.length; i++) { localObject1 = this.interfaces[i].getMethods(); for (int k = 0; k < localObject1.length; k++) { addProxyMethod(localObject1[k], this.interfaces[i]); } } //检查所有代理方法的返回类型 for (Iterator localIterator1 = this.proxyMethods.values().iterator(); localIterator1 .hasNext();) { localObject1 = (List) localIterator1.next(); checkReturnTypes((List) localObject1); } Object localObject2; try { //方法中加入构造方法,这个构造方法只有一个,就是一个带有InvocationHandler接口的构造方法 //这个才是真正给class文件,也就是代理类加入方法了,不过还没真正处理,只是先加进来等待循环,构造方法在class文件中的名称描述是<init> this.methods.add(generateConstructor()); //循环代理方法 for (localIterator1 = this.proxyMethods.values().iterator(); localIterator1 .hasNext();) { localObject1 = (List) localIterator1.next(); for (localIterator2 = ((List) localObject1).iterator(); localIterator2 .hasNext();) { localObject2 = (ProxyMethod) localIterator2.next(); //给每一个代理方法加一个Method类型的属性,数字10是class文件的标识符,代表这些属性都是private static的 this.fields.add(new FieldInfo(((ProxyMethod) localObject2).methodFieldName,"Ljava/lang/reflect/Method;", 10)); //将每一个代理方法都加到代理类的方法中 this.methods.add(((ProxyMethod) localObject2).generateMethod()); } } Iterator localIterator2; //加入一个静态初始化块,将每一个属性都初始化,这里静态代码块也叫类构造方法,其实就是名称为<clinit>的方法,所以加到方法列表 this.methods.add(generateStaticInitializer()); } catch (IOException localIOException1) { throw new InternalError("unexpected I/O Exception"); } //方法和属性个数都不能超过65535,包括刚才的接口个数也是这样, //这是因为在class文件中,这些个数都是用4位16进制表示的,所以最大值是2的16次方-1 if (this.methods.size() > 65535) { throw new IllegalArgumentException("method limit exceeded"); } if (this.fields.size() > 65535) { throw new IllegalArgumentException("field limit exceeded"); } //这里是将类名中的.转成成斜线为了写入class文件。 this.cp.getClass(dotToSlash(this.className)); this.cp.getClass("java/lang/reflect/Proxy"); for (int j = 0; j < this.interfaces.length; j++) { this.cp.getClass(dotToSlash(this.interfaces[j].getName())); } this.cp.setReadOnly(); //这里开始真正的写class文件 ByteArrayOutputStream localByteArrayOutputStream = new ByteArrayOutputStream(); Object localObject1 = new DataOutputStream(localByteArrayOutputStream); try { //写入class文件的标识号,标识这是一个class文件 ((DataOutputStream) localObject1).writeInt(-889275714); //次版本号0 ((DataOutputStream) localObject1).writeShort(0); //主版本号,49代表的是JDK1.5 ((DataOutputStream) localObject1).writeShort(49); //这里写入的是常量池,包括一些属性名称,类名称,方法描述符,属性描述符等等,常量池在加载时会被放到方法区或者说永久代。 this.cp.write((OutputStream) localObject1); //这里写入的是这个类的访问标识,49代表的是public final,也就是说JDK动态代理生成的代理类都是final的 ((DataOutputStream) localObject1).writeShort(49); //写入代理类的类名 ((DataOutputStream) localObject1).writeShort(this.cp .getClass(dotToSlash(this.className))); //写入代理类的父类类名,也就是Proxy类,这个位置的类如果说是JAVA文件,相当于extend后面的类,也就是父类 ((DataOutputStream) localObject1).writeShort(this.cp .getClass("java/lang/reflect/Proxy")); //写入代理类所实现的接口数量 ((DataOutputStream) localObject1) .writeShort(this.interfaces.length); //写入代理类所实现的接口类名,同样的,对于JAVA文件来说,相当于implements后面的接口,也就是实现的接口 for (int m = 0; m < this.interfaces.length; m++) { ((DataOutputStream) localObject1).writeShort(this.cp .getClass(dotToSlash(this.interfaces[m].getName()))); } //写入属性个数 ((DataOutputStream) localObject1).writeShort(this.fields.size()); //写入属性描述 for (Iterator localIterator3 = this.fields.iterator(); localIterator3 .hasNext();) { localObject2 = (FieldInfo) localIterator3.next(); ((FieldInfo) localObject2) .write((DataOutputStream) localObject1); } //写入方法个数 ((DataOutputStream) localObject1).writeShort(this.methods.size()); //写入方法描述,方法的code属性,以及构造方法和类构造方法都在这里被写入了。 for (localIterator3 = this.methods.iterator(); localIterator3 .hasNext();) { localObject2 = (MethodInfo) localIterator3.next(); ((MethodInfo) localObject2) .write((DataOutputStream) localObject1); } //结束 ((DataOutputStream) localObject1).writeShort(0); } catch (IOException localIOException2) { throw new InternalError("unexpected I/O Exception"); } return localByteArrayOutputStream.toByteArray(); }
其实代理类的class文件并不复杂,还是有很多规律可循的,所以上述过程基本上可以让各位了解下JDK动态代理生成代理类时都生成了什么东西。
下面我们可以调用下JDK中生成Class文件的方法,并且写入到本地文件,然后使用反编译工具来看一下生成的代理类到底是什么样子的。下面是生成文件的测试类。我们暂且将生成的类名写成TestProxy,代理的接口就是我们上面的TestInterface。如下。import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import sun.misc.ProxyGenerator; public class CreateClassTest { public static void main(String[] args) throws IOException { byte[] classFile = ProxyGenerator.generateProxyClass("TestProxy", new Class[]{TestInterface.class}); File file = new File("F:/TestProxy.class"); FileOutputStream fos = new FileOutputStream(file); fos.write(classFile); fos.flush(); fos.close(); } }生成后,我们反编译过来会是如下格式的JAVA文件。我加入了注释,大致说明了下文件中生成的部分与刚才分析的时候写入的过程的对应关系。
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; //public final的,继承Proxy,实现你传入的接口 public final class TestProxy extends Proxy implements TestInterface { //private static 的Method属性,对应所有方法 private static Method m1; private static Method m5; private static Method m3; private static Method m4; private static Method m0; private static Method m2; //唯一的构造方法,需要一个InvocationHandler接口传入 public TestProxy(InvocationHandler paramInvocationHandler) throws { super(paramInvocationHandler); } //重写Object的三个方法 public final boolean equals(Object paramObject) throws { try { return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue(); } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final void method3() throws { try { this.h.invoke(this, m5, null); return; } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } //代理的三个方法,回调传入的InvocationHandler的invoke方法 public final void method1() throws { try { this.h.invoke(this, m3, null); return; } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final void method2() throws { try { this.h.invoke(this, m4, null); return; } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final int hashCode() throws { try { return ((Integer)this.h.invoke(this, m0, null)).intValue(); } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final String toString() throws { try { return (String)this.h.invoke(this, m2, null); } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } //这个就是刚才this.methods.add(generateStaticInitializer());这一句话所加入的静态初始化块,初始化每一个属性 static { try {//每一个属性所代表的Method都是与上面加入代理方法列表时与固定类绑定的,这是class文件中的格式,方法要与固定的类绑定 m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); m5 = Class.forName("TestInterface").getMethod("method3", new Class[0]); m3 = Class.forName("TestInterface").getMethod("method1", new Class[0]); m4 = Class.forName("TestInterface").getMethod("method2", new Class[0]); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); return; } catch (NoSuchMethodException localNoSuchMethodException) { throw new NoSuchMethodError(localNoSuchMethodException.getMessage()); } catch (ClassNotFoundException localClassNotFoundException) { throw new NoClassDefFoundError(localClassNotFoundException.getMessage()); } } }看到这里就知道invoke方法是干嘛的了,其实就是生成的代理类对每一个方法的处理就是回调invoke方法。从生成的代理类源文件中也可以发现,每一个Method除了hashCode,toString和equals外,都是与所属的接口绑定的,所以这也就解释了为什么我们不实现这个接口,只传入进入的话,不能直接使用method.invoke,而是要转成source对应的method才可以调用。
以上源码分析,说实话我只看懂大概,先转存,以后慢慢看
相关推荐
代理模式是一种设计模式,它在软件工程中扮演着重要的角色,允许我们为其他对象提供一个替代接口,以控制对原始对象的访问。这种模式的主要目的是为了增加灵活性、安全性或者在不修改原有对象的情况下,增强或扩展其...
代理模式是设计模式的一种,它提供了一种对目标对象进行增强或者控制访问的方式。在本实例中,我们将深入探讨Java中的代理模式及其应用。 代理模式的核心思想是为一个对象创建一个代理对象,这个代理对象在客户端和...
代理模式是设计模式中的一种结构型模式,它在对象交互中起到了中介的作用,允许通过代理对象来控制对原对象的访问。代理模式的核心思想是为一个对象提供一个替身,以便增加新的功能或者控制对原对象的访问。这种模式...
代理模式是设计模式的一种,它的主要目的是在不改变原有对象的基础上,为一个对象提供额外的功能或者控制对这个对象的访问。在Android开发中,代理模式的应用尤为常见,尤其在处理复杂的业务逻辑、网络请求、界面...
SignalR提供了两种主要的工作模式:代理模式和非代理模式。这两种模式在实现上有所不同,各自具有优缺点,适用于不同的场景。 **1. 代理模式(Proxy Mode)** 在代理模式下,SignalR为每个Hub(服务端的业务逻辑...
代理模式是一种常用的设计模式,它在软件开发中扮演着重要的角色,特别是在iOS平台的应用程序设计中。代理模式的核心思想是为一个对象提供一个替身或代理,以控制对这个对象的访问。这种模式允许我们通过代理来间接...
在Java编程中,代理模式是一种常用的面向对象设计模式,它允许我们为一个对象提供一个代理以控制对该对象的访问。代理模式通常用于增加额外的功能,如日志、权限检查等,或者为了创建虚拟代理以提高性能。以下是Java...
**Java设计模式——代理模式详解** 代理模式是软件设计模式中的一个重要组成部分,它在Java编程中扮演着举足轻重的角色。代理模式的核心思想是为一个对象提供一个替身,这个替身即代理对象,代理对象可以控制对原...
代理模式是一种设计模式,它在软件工程中扮演着重要的角色,允许我们为其他对象提供一个替代接口,以控制对原对象的访问。这种模式的主要目的是为了增加灵活性、安全性或者为对象提供额外的功能,同时保持客户端代码...
**设计模式之代理模式(Proxy Pattern)** 设计模式是软件工程中的一种最佳实践,它是在特定情境下解决常见问题的模板。代理模式是其中一种行为设计模式,它的核心思想是为一个对象提供一个替身或者代理,以控制对...
**设计模式实现——代理模式** 在软件工程中,设计模式是一种通用可重用的解决方案,它描述了在特定上下文中经常出现的问题以及该问题的解决方案。代理模式是设计模式的一种,它提供了一种对目标对象的间接访问方式...
代理模式是一种设计模式,属于结构型模式之一,其主要目的是为其他对象提供一个代理,以控制对该对象的访问。在实际应用中,代理模式能够帮助我们实现如下的功能: 1. 远程代理:代理对象可以代表一个位于远程系统...
在这个“Java设计模式-代理模式例子”中,我们将深入探讨代理模式的概念、实现方式以及它在实际开发中的应用。 代理模式的核心思想是为一个对象提供一个替身,这个替身即代理对象,代理对象控制对原对象的访问。在...
代理模式在软件设计中是一种常用的设计模式,尤其在Android开发中,它可以帮助我们实现复杂的控制逻辑,隔离复杂性,以及提供额外的功能。在Android上下文中,代理模式常常用于数据加载、权限控制、事件处理等方面。...
代理模式是一种设计模式,它是结构型模式之一,主要用于在客户端和目标对象之间建立一个代理对象,以便控制对目标对象的访问。在C++中,代理模式可以用来为其他对象提供一种代理以控制对这个对象的访问,或者增加...
### Java代理模式与Java动态代理详解 #### 一、代理模式概述 代理模式是一种软件设计模式,它在客户端和目标对象之间提供了一种间接层。这种模式的主要目的是控制客户端对目标对象的访问,并且可以在不修改原有...
代理模式是一种常用的设计模式,它在软件开发中扮演着重要角色,允许我们通过一个代理类来控制对原对象的访问。在《设计模式:可复用面向对象软件的基础》(通常称为GoF设计模式)中,代理模式被定义为“为其他对象...
代理模式(Proxy) 定义: 为其他对象提供一种代理以控制对这个对象的访问 结构: 由三部分组成 1.RealSubject(真实对象): 真正会调用到的对象 2.Proxy(代理对象): 代理真实对象的地方 3.Subject(共同点): 代理对象...
在IT行业中,代理模式是一种常见的设计模式,它允许我们在不修改原有对象的基础上,为对象添加新的功能或控制访问。在本示例中,我们将重点讨论如何在Java环境下使用代理模式来实现代理逻辑,特别是在CAS(Central ...