1、代理模式
从设计模式的角度看,代理模式用于解耦两个对象,代理作为中介桥接客户(调用者)和业务逻辑类。通常代理是已存在的类,它被JVM加载到内存后实例化并使用,也可以在运行时动态生成,从而使得代理的应用更加灵活。其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别(透明的)。通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间,从而在设计上获得了更大的灵活性。如代理对象则可以封装一些内部的处理逻辑(一些新增的功能如访问控制、日志、缓存、授权等)。
Java 动态代理机制以巧妙的方式近乎完美地实践了代理模式的设计理念。
2、传统的代理模式
在客户类(调用者)和业务逻辑类(被调用者,被代理者)之间添加附加的类Proxy(代理者,一般会和被代理者实现相同的接口),实现传统代理模式。
如下图中的代理类Proxy和Car都实现了IVehicle接口:
public class VehicleProxy implements IVehicle{
private IVehicle v;
public VehicleProxy(IVehicle v){this,v=v;}
public void start(){
System.out,println(“VehicleProxy之前”);
v.start();
System.out,println(“VehicleProxy之后”);
}
//stop(), forward(), …
}
3、动态代理的原理
JDK5引入了动态代理。允许开发人员在运行时刻随时随地创建出代理类及其对象,动态创建出实现多个接口的代理类,每个代理对象关联一个表示内部处理逻辑的InvocationHandler接口的实现。
当客户调用代理对象所代理接口中的方法时,调用信息会被传递给InvocationHandler接口的invoke()方法。invoke()方法的参数中可以获取到代理对象、方法对应的Method对象和调用的实际参数,其返回值被返回给使用者(是谁?)。
这种做法相当于对方法调用进行了拦截,AOP就是基于这一思想的实现框架。
4、动态代理的实现
若使用动态代理实现同样的功能,首先要定义实现InvocationHandler接口的类VehicleHandler。
定义了动态代理后,客户端的调用方式如图:
这里看似没有产生好处,还要编写调用处理类(Invocation Handler),那么为什么还要使用动态代理?是为了产生通用委托类(添加日志等功能)~
5、解析Proxy类中public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法:
/*将VehicleHandler绑定给IVehicle接口*/
ClassLoader cl=IVehicle.class.getClassLoader();
IVehicle v=(IVehicle) Proxy.newProxyInstance(
cl,new Class[]{IVehicle.class},
new VehicleHandler(Ivehicle c)
);
这个方法Returns an instance of a proxy class for the specified interfaces that dispatches method invocations to the specified invocation handler.
(它返回指定接口的代理类的实例对象,这个(代理类?)将方法调用分派给指定的调用处理程序)
loader, the class loader to define the proxy class.
interfaces, the list of interfaces for the proxy class to implement.
h , the invocation handler to dispatch method invocations to 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.
6、关于ClassLoader类
ClassLoader类就是用来动态加载class文件到内存当中用的。
当我们写好一个Java程序之后,不是管是CS还是BS应用,都是由若干个.class文件组织而成的一个完整的Java应用程序,当程序在运行时,即会调用该程序的一个入口函数来调用系统的相关功能,而这些功能都被封装在不同的class文件当中,所以经常要从这个class文件中要调用另外一个class文件中的方法,如果另外一个文件不存在的,则会引发系统异常。
而程序在启动的时候,并不会一次性加载程序所要用的所有class文件,而是根据程序的需要,通过Java的类加载机制(ClassLoader)来动态加载某个class文件到内存当中的,从而只有class文件被载入到了内存之后,才能被其它class所引用。所以ClassLoader就是用来动态加载class文件到内存当中用的。