动态代理

代理

代理是常用的设计模式之一,它可以提供额外的或不同的操作,它能够方便的将额外的操作从“实际”对象中分离到不同的地方。
换句话说:你希望某个对象调用某个方法之前或之后完成一些特定操作,就可以使用代理。代理可以提供了这些特定操作,并将这些特定操作从实际的对象中分离。

代理分为两种:

  1. 静态代理
  2. 动态代理

静态代理

静态代理就是设计模式中的代理模式,我们需要自己定义代理类:

interface Subproject{
    void now();
}

class RealProject implements Subproject{

    @Override
    public void now() {
        System.out.println("now");
    }
}

//代理类
class ProxyProject implements Subproject{
    private RealProject realProject;

    public ProxyProject(RealProject realProject) {
        this.realProject = realProject;
    }

    public void before(){
        System.out.println("before");
    }

    public void after(){
        System.out.println("after");
    }
    @Override
    public void now() {
        before();
        realProject.now();
        after();
    }
}

public class Client {
    public static void main(String[] args) {
        RealProject realProject = new RealProject();
        
        ProxyProject proxyProject = new ProxyProject(realProject);
        proxyProject.now();
    }
}

//结果
before
now
after

我希望RealProject对象在调用now()方法之前和之后做一些额外的操作:before()和after()。使用代理,代理类ProxyProject提供了这些额外的操作并将这些操作从RealProject对象中分离出来。

动态代理

Java中的动态代理比代理的思想更向前迈了一步,因为它可以动态的创建代理并可以动态的处理对所代理方法的调用。

要实现动态代理,需要依赖两个类:

  • InvocationHandler :每个代理对象都有一个相关联的调用处理程序,当代理对象调用方法时,方法调用被编码并调度到此接口的invoke方法。
  • Proxy:代理对象,调用Proxy.newProxyInstance()可以创建代理对象。

我们将上述静态代理改为动态代理:

interface Subproject{
    void now();
}

class RealProject implements Subproject{

    @Override
    public void now() {
        System.out.println("now");
    }
}

//调用处理类:每个代理对象都有一个关联的调用处理程序
class DynamicProxyProject implements InvocationHandler {

    private RealProject realProject;

    public DynamicProxyProject(RealProject realProject) {
        this.realProject = realProject;
    }

    public void before(){
        System.out.println("before");
    }
    public void after(){
        System.out.println("after");
    }
    /*
        当在代理对象上调用一个方法时,方法调用被编码并调度到其调用处理程序的invoke方法。
        invoke()有三个参数:
        proxy:调用方法的代理对象。
        method:代理对象调用的方法的方法实例。
        args:代理对象调用的方法的参数。
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object invoke = method.invoke(realProject, args);
        after();
        return invoke;
    }
}

public class Client {

    public static void main(String[] args) {
        //实际对象
        RealProject realProject = new RealProject();

        InvocationHandler invocationHandler = new DynamicProxyProject(realProject);

        ClassLoader classLoader = realProject.getClass().getClassLoader();
        Class[] interfaces = realProject.getClass().getInterfaces();


        /*
            用Proxy.newProxyInstance()来创建一个代理对象的实例。
            此方法有三个参数:
            ClassLoader: 用哪个类加载器去加载代理对象
            Class<?>[] interfaces: 动态代理类需要实现的接口
            InvocationHandler:动态代理对象在执行方法时,会调用此接口中的的invoke方法去执行.
         */
        Subproject proxy = (Subproject) Proxy.newProxyInstance(classLoader,interfaces,invocationHandler);
        /*
           当在proxy调用now()方法时,方法调用被编码并调度到InvocationHandler中的invoke方法。
         */
        proxy.now();
    }
}

静态代理中我们需要手动创建代理类并在代理类中调用实际对象的方法。
动态代理中我们通过Proxy类的newProxyInstance()方法创建代理对象,此代理对象调用方法时,方法调用被编码并调度到InvocationHandler中的invoke方法。所以要实现InvocationHandler接口中的invoke方法。

posted @ 2020-11-01 10:27  xxgbl  阅读(111)  评论(0)    收藏  举报