一。首先需要了解下面3个类的API:java系统支持的代理就是这3个类+反射来实现。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
二。下面的这段测试代码,目的就是:将一个ArrayList对象的操作进行代理,每个method前后都输出一行字符串。
核心代码是
Class clz = ArrayList.class;
Object proxyed_Object = Proxy.newProxyInstance(clz.getClassLoader(),
clz.getInterfaces(), new MyInvocationHandle(new ArrayList(10)));
生成一个ArrayList的代理的对象。
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
/**
* DEMO:测试java中的代理
*
* 代理了一个ArrayList对象,并在调用方法前后各加了一个systemout输出
* @author wei.songw
*
*/
public class MyInvocationHandle implements InvocationHandler {
//对代理对象的引用.
private List aList;
/**
* 构造器。
* @param list 代理对象
*/
public MyInvocationHandle(Object list) {
this.aList = (List) list;
}
/**
* InvocationHandler的方法实现
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//方法前调用,插入一段消息
System.out.println("before : "+method.getName());
//调用方法.
Object object = method.invoke(aList, args);
//方法后调用,插入一段消息
System.out.println("after : "+method.getName());
return object;
}
public static void main(String[] args) {
//需要代理一个ArrayList对象,因此按照API构造一个Proxy对象
//,同时也初始化了处理Proxy的MyInvocationHandle对象
Class clz = ArrayList.class;
Object proxyed_Object = Proxy.newProxyInstance(clz.getClassLoader(),
clz.getInterfaces(), new MyInvocationHandle(new ArrayList(10)));
//TEST1:查看一下代理生成类的接口???
// Class<!---->[] itfs = proxyed_Object.getClass().getInterfaces();
// for (int i = 0; i < itfs.length; i++) {
// System.out.println(itfs[i].getName());
// }
//注意!这里操作的是代理类!
List list = (List)proxyed_Object;
list.add(Integer.valueOf(10));
//TEST2:输出一下list的大小,确认add方法被调用
// System.out.println(list.size());
}
}
输出如下:
before : add
after : add
如果将TEST2段代码去掉注释,可以看到如下输出:
before : add
after : add
before : size
after : size
1
证明add方法确实被调用了。
三。代理模式的结构图(UML+时序图)
通过UML图可以看到代理类和被代理实际对象实现同一接口/或者一个抽象类,因此外部调用Subject,是感觉不到代理类的存在。
问题出现了:上面的测试代码中,被代理ArrayList对象,并未与调用者MyInvocationHandle实现同样的接口 。那是怎么实现代理模式的呢?
看Proxy类的文档,写到:
/**
* Returns an instance of a proxy class for the specified interfaces
* that dispatches method invocations to the specified invocation
* handler. This method is equivalent to:
* * Proxy.getProxyClass(loader, interfaces).
* getConstructor(new Class[] { InvocationHandler.class }).
* newInstance(new Object[] { handler });
*
*
* Proxy.newProxyInstance
throws
* IllegalArgumentException
for the same reasons that
* Proxy.getProxyClass
does.
*
* @param loader the class loader to define the proxy class
* @param interfaces the list of interfaces for the proxy class
* to implement
* @param h the invocation handler to dispatch method invocations to
* @return a proxy instance with the specified invocation handler of a
* proxy class that is defined by the specified class loader
* and that implements the specified interfaces
* @throws IllegalArgumentException if any of the restrictions on the
* parameters that may be passed to getProxyClass
* are violated
* @throws NullPointerException if the interfaces
array
* argument or any of its elements are null
, or
* if the invocation handler, h
, is
* null
*/
返回一个实现指定接口的代理类实例,并绑定方法调用到一个指定的invocation handler.
如果将TEST1段注释去掉,可以看到这个代理对象实现了如下接口:
java.util.List java.util.RandomAccess java.lang.Cloneable java.io.Serializable
并且Proxy.newProxyInstance等同于
* Proxy.getProxyClass(loader, interfaces).
* getConstructor(new Class[] { InvocationHandler.class }).
* newInstance(new Object[] { handler });
这里是部分源码:
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");
}
}
}
通过时序图可以看到,外部Client和代理类打交道,而代理类在调用实际对象时可以增加一些有益的操作。
分享到:
相关推荐
java.proxy,代理模式源码,设计模式,apache开源项目源码commons-proxy-1.0-src 各种代理模式操作的工具类源码以及代理模式案例源码,你会从中得到意想不到的效果! apache开源组织开发的开源项目源码,其优良的代码...
Proxy模式是设计模式中的一种,它提供了一种对对象访问的控制手段,使得在不修改原有对象的基础上,可以通过代理对象来扩展或增强原有对象的功能。在Java编程中,Proxy模式的应用非常广泛,尤其是在处理远程调用、...
我自己用eclipse写的java代码,可以直接用eclipse导入,也可以直接用java -jar proxy_sample.jar执行 代码量很小,尽量通过注释进行说明 本例实现了InvocationHandler...在研究代理模式(Proxy模式)的朋友可以交流一下
总结来说,"proxy.rar"压缩包提供了Java编程中三种代理模式的源代码实例,通过学习这些代码,开发者可以深入理解代理模式的原理和实现,同时掌握泛型在实际项目中的应用。对于提高代码的可扩展性和可维护性,这些都...
在这个“Java设计模式-代理模式例子”中,我们将深入探讨代理模式的概念、实现方式以及它在实际开发中的应用。 代理模式的核心思想是为一个对象提供一个替身,这个替身即代理对象,代理对象控制对原对象的访问。在...
在Java中,动态代理是代理模式的一种实现方式,它允许我们在运行时创建代理对象,这种方式比静态代理更加灵活。动态代理在JDK 1.3及以后的版本中得到了支持,主要涉及到三个核心类:`Proxy`、`InvocationHandler`和`...
在Java中,动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。Proxy类是用于创建一个代理对象,而InvocationHandler接口则定义了代理对象调用方法时的行为。 1. **...
Java中有两种方式来实现动态代理,一种是使用JDK中的Proxy类,另一种是使用CGLIB库。使用JDK中的Proxy类,可以生成代理对象,并将其绑定到原始对象上。使用CGLIB库,可以生成代理对象,并将其绑定到原始对象上,同时...
Java设计模式精讲-代理模式
### Java代理模式与Java动态代理详解 #### 一、代理模式概述 代理模式是一种软件设计模式,它在客户端和目标对象之间提供了一种间接层。这种模式的主要目的是控制客户端对目标对象的访问,并且可以在不修改原有...
在Java中,代理模式可以通过多种方式实现,包括静态代理和动态代理。 在提供的文件列表中,我们可以看到以下几个关键类: 1. `ProxyDisplay`:这个名字暗示了它可能是代理模式中的代理类,用于代表或代替某个实际...
在这个"JAVA设计模式例程-代理模式"的压缩包中,我们可以深入学习如何在Java中实现这一模式。 1. **代理模式的基本概念** 代理模式的核心思想是为一个目标对象创建一个代理对象,代理对象在客户端和目标对象之间起...
在Java中实现代理模式,通常有两种方式:静态代理和动态代理。 首先,我们来看静态代理。静态代理是通过创建一个代理类来实现对目标对象的代理,这个代理类和目标类具有相同的接口,代理类在调用目标对象方法时可以...
1. **静态代理**:在静态代理中,我们需要为每个真实对象创建一个代理对象,并在代理类中实现与真实对象相同的方法。这样,当客户端调用代理对象的方法时,实际上会调用到代理类中相应的方法,从而可以添加额外的...
在Java中,代理模式有静态代理和动态代理两种实现方式。本篇将重点讨论"动态代理",这是一种在运行时创建代理对象的技术,使得我们可以在程序运行过程中,根据需要动态地生成具有额外功能的代理类。 动态代理主要由...
在Java中,代理模式有静态代理和动态代理两种主要实现方式,它们都是为了在客户端与目标对象之间插入一个代理对象,从而实现对目标对象的间接访问。 ### 静态代理 静态代理是程序员手动创建代理类并实现相同接口的...
在Java中,代理模式可以通过多种方式实现,包括静态代理、动态代理(JDK动态代理和CGLIB动态代理)等。 **静态代理** 静态代理是最基础的代理形式,需要手动创建一个代理类,该类继承或实现与目标类相同的接口,并...
2. 结构型模式:如代理模式(Proxy)、适配器模式(Adapter)、装饰器模式(Decorator)、桥接模式(Bridge)、组合模式(Composite)、外观模式(Facade)和享元模式(Flyweight)。这些模式主要处理对象之间的关系...
在Java编程中,代理模式是一种常用的面向对象设计模式,它允许我们为一个对象提供一个代理以控制对该对象的访问。代理模式通常用于增加额外的功能,如日志、权限检查等,或者为了创建虚拟代理以提高性能。以下是Java...
总结来说,Java动态代理通过`Proxy`和`InvocationHandler`提供了灵活的代码扩展机制,可以在运行时为对象创建代理,实现在不修改原有代码的基础上添加额外功能。这在处理需要拦截和增强的对象时非常有用,例如日志...