代理模式是Java 设计模式中很常用的一种设计模式,它的特点是代理类和被代理类具有相同的接口,这样代理类才能代理被代理类。当我们执行被代理类的某些方法的时候,委托给代理类,代理类可以在被代理类方法的执行前后多做一些事情。类似于Spring中的AOP
代理类可分为两种形似。一种为静态代理类,由程序开发人员自己编写代理类;另外一种为动态代理类,在程序运行时,运用反射机制动态生成。动态代理类不需要程序开发人员编写源代码。运用Java的反射机制生成,扩展容易。
java.lang.reflect 包中的Proxy类和InvocationHandler接口提供了生成动态代理类的功能。
Proxy类通过静态方法创建代理类和代理类的实例
下面通过一个简单的实例讲解如何使用动态代理
首先创建一个简单的接口IHello,其中只有一个方法sayHello,无论是常规类,还是代理类都需要实现此接口。
- <font color="black">package dynamicpro;
- public interface IHello {
- public void sayHello();
- }</font>
复制代码 创建实现此接口的类HelloImpl,此类为日后的被代理类
- <font color="black">package dynamicpro;
- public class HelloImpl implements IHello {
- public HelloImpl() {
- }
- public void sayHello() {
- System.out.println("Hello World");
- }
- }</font>
复制代码 下面通过工厂方法创建动态代理类及其实例
- <font color="black">package dynamicpro;
- import java.lang.reflect.*;
- public class HelloFactory {
- public HelloFactory() {
- }
- public static IHello getHelloProxy(final IHello hello){
- InvocationHandler handler=new InvocationHandler(){
- public Object invoke(Object proxy, Method method, Object[] args) throws
- Throwable {
- System.out.println("before calling "+method);
- Object result=method.invoke(hello,args);
- System.out.println("after calling "+method);
- return result;
- }
- };
- Class classType=IHello.class;
- return (IHello)Proxy.newProxyInstance(classType.getClassLoader(),new Class[]{classType},handler);
- }
- }</font>
复制代码
创建动态代理类时,使用Proxy.newProxyInstance方法。此方法需要InvocationHandler接口类型的参数。所以创建InvocationHandler对象,并实现invoke方法。当动态代理类代理其他的类的时候,调用此方法。invoke方法的三个参数分别为:代理类对象,调用的被代理类的方法,方法的参数。我们可以在invoke方法中编写适当的代码,当执行被代理类的方法的时候多做置前和置后的一些处理。比如这里只是在方法的执行前后输出一些内容。
Proxy.newProxyInstance方法返回动态代理类的实例,第一个参数指名被代理类的类型,显然是IHello接口类型,第二个参数是被代理类所实现的所有的接口类型。显然也是IHello.class。第三个参数即为刚才创建的InvocationHandler对象,当执行被代理类的方法时候,调用其中的invoke方法。
编写测试类进行测试:
- <font color="black">package dynamicpro;
- public class HelloTest {
- public HelloTest() {
- }
- public static void main(String[] args) {
- IHello hello=new HelloImpl();
- IHello helloProxy=HelloFactory.getHelloProxy(hello);
- helloProxy.sayHello();
- }
- }</font>
复制代码 运行结果如下:
- <font color="black">before calling public abstract void
- dynamicpro.IHello.sayHello()
- Hello World
- after calling public abstract
- void dynamicpro.IHello.sayHello()</font>
复制代码
|