一、结构型
1、代理模式(Proxy)
源码地址:https://github.com/Shenpotato/proxydemo
RealSubject为委托类,Proxy为代理类,他们同时继承于Subject接口,代理类持有委托类的实例,代为执行具体类的方法,正如图中的Request()方法;相比于直接实例化RealSubject对象,通过Proxy进行代理,使具有间接性,可以附加多种用途。
(1)静态代理模式(staticproxydemo)
由程序员创建或特定工具自动生成源代码,也就是在编译时就已经将接口,被代理类,代理类等确定下来。在程序运行之前,代理类的.class文件就已经生成。
在源码中,Person接口为上图所示的Subject;Student为RealSubject,是具体实现类;StudentProxy为代理类,在StudentProxy中实现Student具体类的实例化,代为执行Student中的givemoney()方法。
(2)动态代理模式(dynamicproxydemo)
ThreadLocal详解:http://en.eywedu.net/Soft/index.html
与静态代理模式不同,代理类在程序运行时创建的代理方法称为动态代理。动态代理中,代理类不在java代码中定义,而是由java代码的指示动态生成的。
还是以源码为例,与静态代理模式一样,Person为接口,Student为委托代理类,givemnoney()为Person接口的实现方法,MonitorMethodTime为测试方法执行时间的类。与静态代理模式不同,我们的givemoney()方法,以及其余所有方法,都在实现InvocationHandler接口的StudentInvocationHandler中的invoke方法中实现;代理类的生成是通过主类中调用Proxy.newProxyInstance()实现。接下来我们解释一下InvocaitonHandler中的invoke()和Proxy.newProxyInstance()两个函数。
A.InvocationHandle.invoke()
public class StudentInvocationHandle<T> implements InvocationHandler {
//InvocationHandler持有的被代理对象
T target;
public StudentInvocationHandle(T target) {
this.target = target;
}
/*
*所有执行代理对象的方法都会被替换成为invoke方法
* proxy表示动态代理的对象
* method:表示正在执行的方法
* args:表示调用目标方法时传入的实参
* */
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理执行"+method.getName()+"方法");
//代理过程中插入监测方法,计算该方法耗时
//通过method,invoke方法实现代理对象的方法
Object result = method.invoke(target,args);
return result;
}
}
其中method.invoke()方法将所代理对象的方法实现。
B.Proxy.newProxyInstance()
public class TestProxy {
public static void main(String[] args) {
//创建一个实例对象,这个对象是被代理的对象
Person shenpotato = new Student("Shenpotato");
//创建一个与代理对象相关联的InvocationHandler,并实现传参
InvocationHandler stuHandler = new StudentInvocationHandle<Person>(shenpotato);
/*
* 创建一个代理对象来stuProxy来代理shenpotato,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
* newProxyInstance将实例化方法封装
* newProxyInstance机制介绍:
* public static Object newProxyInstance(ClassLoader loader,实现一个类加载器,在此实例中实现Person接口的类加载器
Class<?>[] interfaces, 此类实现的各个接口
InvocationHandler h 创建的用来代理该具体类的代理对象
)
* */
Person stuProxy = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(),new Class<?>[]{Person.class}, stuHandler);
//执行捐献方法
stuProxy.givemoney();
}
}