Fork me on GitHub

【Java Proxy Pattern】Java的代理模式

Java的代理模式

什么是代理模式[Proxy Pattern]?

代理模式就是为了在其他对象访问一个对象时,提供一种代理,而不是直接访问该对象。
有点像在外部进行了一层包裹。
这个代理模式,和装饰器模式Decorator Pattern的区别在于proxy是为了控制,decorator是为了增强功能。

静态代理和动态代理

  • 静态代理类就是类已经生成好了,而不是在程序运行时生成的。
    静态一旦写完,一般就代理一个固定的类。

  • 动态代理类在很多场景下在client和target之间充当一个中介者的角色。动态代理类时在运行时生成字节码,

接口

/**
* Interface IVehicle.
*/
public interface IVehicle {
    public void start();
    public void stop();
    public void forward();
    public void reverse();
    public String getName();
}

target class

/**
* Class Car
*/
public class Car implements IVehicle {
    private String name;
    public Car(String name) {this.name = name;}
    public void start() {
    System.out.println("Car " + name + " started");
}
// stop(), forward(), reverse() implemented similarly.
// getName() not shown.
}

client

/**
* Class Client1.
* Interacts with a Car Vehicle directly.
*/
public class Client1 {
    public static void main(String[] args) {
        IVehicle v = new Car("Botar");
        v.start();
        v.forward();
        v.stop();
    }
}

代理类

/**
* Class VehicleProxy.
*/
public class VehicleProxy implements IVehicle {
    private IVehicle v;
    public VehicleProxy(IVehicle v) {this.v = v;}
    public void start() {
    System.out.println("VehicleProxy: Begin of start()");
    v.start();
    System.out.println("VehicleProxy: End of start()");
    }
    // stop(), forward(), reverse() implemented similarly.
    // getName() not shown.
}

代理类的client2

/**
* Class Client2.
* Interacts with a Car Vehicle through a VehicleProxy.
*/
public class Client2 {
    public static void main(String[] args) {
        IVehicle c = new Car("Botar");
        IVehicle v = new VehicleProxy(c);
        v.start();
        v.forward();
        v.stop();
    }
}

动态代理

  • 动态代理是在运行时实现了目标类的一系列接口
  • 代理instance是代理类的一个instance
  • 每一个代理实例都会调用一个实现InvoicationHandler接口的handler object
  • 代理实例上的方法调用通过他的代理接口调用实例的invocation handler
  • 代理类的创建是通过 java.lang.reflect.Proxy
  • 代理类的名字是以$Proxy开头
  • 当代理类创建的时候, 所指定的接口会被实现。
  • 当代理类创建时实现了所有接口, 代理类调用 getInterfaces()会返回一个包含所有接口的接口数组。
  • 每一个代理类有一个public的构造函数 需要一个实现InvocationHandler接口的handler 作为参数。

getProxyClass

 public static Class getProxyClass(ClassLoader loader,
Class[] interfaces)
throws IllegalArgumentException

通过类加载器,接口数组,返回一个代理类。

Proxy构造一个Proxy 实例

protected Proxy(InvocationHandler ih)

isProxyClass 判断是否一个代理类。

public static boolean isProxyClass(Class c)

newProxyInstance

 public static Object newProxyInstance(ClassLoader loader,
Class[] interfaces,
InvocationHandler ih)
throws IllegalArgumentException

以下2个写法是等价的

Proxy.newProxyInstance(cl, interfaces, ih);
Proxy.getProxyClass(cl,
interfaces).getConstructor(new Class[] {
InvocationHandler.class }).newInstance(new
Object[] {ih});

getInvocationHandler 从指定的proxy 返回一个调用invocation handler

public static InvocationHandler getInvocationHandler
(Object proxy)
throws IllegalArgumentException

invoke 处理代理实例上的方法调用并且返回object
proxy是代理类,method是方法名,args是方法对应的参数

public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable

所以这样一来,handler就是这样

/**
* Class VehicleHandler.
*/
public class VehicleHandler implements InvocationHandler {
    private IVehicle v;
    public VehicleHandler(IVehicle v) {this.v = v;}
    public Object invoke(Object proxy, Method m, Object[] args)
    throws Throwable {
        System.out.println("Vehicle Handler: Invoking " +
        m.getName());
        return m.invoke(v, args);
    }
}

代理类的 client3

/**
* Class Client3.
* Interacts with a Car Vehicle through a dynamically
* generated VehicleProxy.
*/
public class Client3 {
    public static void main(String[] args) {
        IVehicle c = new Car("Botar");
        ClassLoader cl = IVehicle.class.getClassLoader();
        IVehicle v = (IVehicle) Proxy.newProxyInstance(cl,
        new Class[] {IVehicle.class}, new VehicleHandler(c));
        v.start();
        v.forward();
        v.stop();
    }
}
posted @ 2020-08-27 16:52  WilliamCui  阅读(156)  评论(0编辑  收藏  举报