反射与代理设计模式-动态代理设计模式
1、动态代理设计模式的核心特点:一个代理类可以代理所有需要被代理接口的子类对象。

2、如果要想进行动态代理设计的实现,代理类不再具体实现于某一个接口。
我们需要实现InvocationHandler动态代理实现标识接口,只有实现此接口的子类才具备动态代理的功能。
public Object invoke(Object proxy, Method method, Object[] args);
invoke()表示的是调用执行的方法,但是所有的代理类返回给用户的接口对象都属于代理对象,当用户执行接口方法的时候所调用的实例化对象就是该代理主题动态创建的一个接口对象。
proxy 表示的是被代理的对象信息。
method 返回的是被调用的方法对象,取得了Method对象意味着可以使用invoke()反射调用方法。
args 标识方法中收到的参数

3、如果要想进行对象的绑定,那么就需要使用到一个Proxy的程序类,这个程序类的主要功能是可以绑定所有的你需要绑定的接口子类的对象,而且这些对象都是根据接口自动创建的,该类有一个动态创建的方法:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException

4、实现真实对象的绑定处理,同时返回代理对象。(这个对象是根据接口定义动态创建形成的代理对象)。

5、保存真实主题对象。
/**
* 实现真实对象的绑定处理,同时返回代理对象
* @param target
* @return 返回一个代理对象(这个对象是根据接口定义动态创建形成的代理对象)
*/
public Object bind(Object target) {
this.target = target; //保存真实主题对象
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}

6、动态代理设计实现:
package com.gwolf.design;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
//代理设计的核心在于需要有一个核心的操作接口
interface ISubject {
//直返是整体的核心业务
public void eat(String msg,int num);
}
class RealSubject implements ISubject {
@Override
public void eat(String msg,int num) {
System.out.println("饿了一定吃"+num+"分量的:" + msg);
}
}
class ProxySubject implements InvocationHandler {//动态代理类
private Object target; //绑定任意的接口对象,使用Object描述
/**
* 实现真实对象的绑定处理,同时返回代理对象
* @param target
* @return 返回一个代理对象(这个对象是根据接口定义动态创建形成的代理对象)
*/
public Object bind(Object target) {
this.target = target; //保存真实主题对象
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
public void prepare() {
System.out.println("【ProxySubject】准备食材!");
}
public void over() {
System.out.println("【ProxySubject】洗碗完毕");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(proxy.getClass());
System.out.println(method);
System.out.println(Arrays.toString(args));
this.prepare();
Object ret = method.invoke(this.target, args);
this.over();
return ret;
}
}
public class ProxyDesign {
public static void main(String[] args) {
ISubject subject = (ISubject)new ProxySubject().bind(new RealSubject());
subject.eat("吃肉", 20);
}
}
