动态代理模式 Dynamic Proxy Pattern
个人总结:相比较与静态代理模式,动态模式更加灵活。 ,可以对不同的对象进行代理,。对不同的方法进行代理。通过比较会发现,静态代理的做法是将代理与被代理的对象写死,不灵活。而动态代理则通过实现InvocationHandler的invoke方法,用发射机制灵活地代理多种实现相同接口的对象, 动态代理是框架Spring的基石。
下面以一个简单例子说明:
Step One:
创建被代理的类和接口。即是创建真实角色和抽象角色。 真实角色实现抽象角色。
package com.master.proxy;
//接口,抽象角色
public interface AbstractProxy {
public abstract void getPhone();
public abstract void getMoney();
}
package com.master.proxy;
// 被代理的类,真实角色,它实现抽象角色AbstractProxy接口
public class RealSub implements AbstractProxy {
@Override
public void getPhone() { // method 1
// TODO Auto-generated method stub
System.out.println("cost 500 RMB");
System.out.println("that's the end");
}
@Override
public void getMoney() { // method 2
System.out.println("say hello.And this is getMoney method");
}
}
Step Two:
创建一个实现了InvocationHandler接口的实现类。它必须实现invoke方法。
package com.master.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ProxyHandle implements InvocationHandler {
private Object proxyy;
public ProxyHandle(Object obj) { //接收传入的被代理的对象
this.proxyy = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("before: " + method); // 打印 调用了哪个对象
method.invoke(proxyy, args);
System.out.println("after: " + method);
return null;
}
}
Step Three:
通过Proxy的静态方法来创建一个运行时的代理对象! 并通过该代理对象调用方法。
Proxy.newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
注意,这个对象也是被宣称实现了抽象角色AbstractProxy接口。仔细分析下JDk中的newProxyInstance函数会发现第二个参数接收的是 interfaces ,也就是创建的新的proxy代理对象也是实现了这些接口的,注意是Class<>类型数组,可以有多个接口。
package com.master.proxy;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
RealSub realSub = new RealSub();
ProxyHandle proxyHandle = new ProxyHandle(realSub);
AbstractProxy obj = (AbstractProxy) Proxy.newProxyInstance(
ProxyHandle.class.getClassLoader(), realSub.getClass()
.getInterfaces(), proxyHandle);// obj是运行时动态生成的。
// getInterfaces宣称实现了哪几种interfaces,则生成实现了哪几接口的代理对象(这里是宣称AbstractProxy接口) 返回值强制为那几种接口的任何一种
obj.getPhone(); // 新产生的代理对象obj调用getPhone方法,实际是交给proxyHandler处理。obj是代理角色!
obj.getMoney();
}
}
这样,通过newProxyInstance方法new出来的新的代理对象obj 也自热而然地实现了了抽象角色AbstractProxy接口。
输出:
before: public abstract void com.master.proxy.AbstractProxy.getPhone()
cost 500 RMB
that's the end
after: public abstract void com.master.proxy.AbstractProxy.getPhone()
before: public abstract void com.master.proxy.AbstractProxy.getMoney()
say hello.And this is getMoney method
after: public abstract void com.master.proxy.AbstractProxy.getMoney()