美文网首页Java
动态代理实战

动态代理实战

作者: 奔跑吧李博 | 来源:发表于2021-06-27 10:54 被阅读0次

动态代理它可以直接给某一个目标(被代理 对象)对象(实现了某个或者某些接口)生成一个代理对象,而不需要代理类存在。
动态代理与代理模式原理是一样的,只是它没有具体的代理类,直接通过反射生成了一个代理对象。

jdk中的动态代理

1、Java.lang.reflect.Proxy类可以直接生成一个代理对象

Proxy.newProxyInstance方法参数介绍

ClassLoader:类加载器
它是用来加载器的,把.class文件加载到内存,形成Class对象!
Class[] interfaces:指定要实现的接口们
InvocationHandler:代理对象的所有方法(个别不执行,getClass())都会调用InvocationHandler的invoke()方法。

2、InvocationHandler方法参数介绍

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

这个invoke()方法在什么时候被调用!在调用代理对象所实现接口中的方法时

Object proxy:当前对象,即代理对象!在调用谁的方法!
Method method:当前被调用的方法(目标方法)
Object[] args:实参!

示例一:

Customer类为需要打官司的顾客,Lawyer为律师类,Lawyer类需要代理Customer打官司。

定义代理类与目标类共同的接口:

interface Law {
    //定义一个打官司的接口,需要实现打官司
    void law();
}

被代理类:某个客户需要打官司

class Customer implements Law {

    @Override
    public void law() {
        System.out.println("上法庭陈述事实");
    }
}

创建实现动态代理的MyHandler类,实现InvocationHandler接口和invoke方法。

/**
 * 实现动态代理的核心接口,动态代理本质采用的java反射机制实现
 */
class MyHandler implements InvocationHandler {
    private Customer  customer;

    public MyHandler(Customer customer) {
        this.customer = customer;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("搜集证据");
        Object obj = method.invoke(customer, args);  //使用反射调用customer中的method方法
        System.out.println("打赢官司");
        return obj;
    }
}

执行测试:

    public static void main(String[] args) {

        //代理目标对象
        Customer customer = new Customer();
        //代理回调类
        MyHandler myHandler = new MyHandler(customer);
        //生成代理对象Proxy通过调用newProxyInstance方法生成代理对象,传入该类的classLoader,实现接口,InvocationHandler
        Law proxy = (Law) Proxy.newProxyInstance(Customer.class.getClassLoader(), customer.getClass().getInterfaces(), myHandler);
        proxy.law();
    }

调用结果:

示例二:

定义代理类与目标类共同的接口:

public interface HelloInterface {
    void sayHello();
}

被代理类:

class Hello implements HelloInterface {
    @Override
    public void sayHello() {
        System.out.println("这里是被代理类Hello");
    }
}

创建实现动态代理的ProxyHandler类,实现InvocationHandler接口和invoke方法。

class ProxyHandler implements InvocationHandler {
    private Object object;

    //需要传入Object类型,任意类型
    public ProxyHandler(Object object) {
        this.object = object;
    }

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

        //invoke中使用反射调用传入的被代理对象的方法
        System.out.println("before invoke" + method.getName());
        method.invoke(object, args);
        System.out.println("after invoke" + method.getName());
        return null;
    }
}

执行测试:

    public static void main(String[] args) {
        HelloInterface hello = new Hello();  //创建需要被代理的Hello类对象

        //此时,不再创建具体的代理对象,而是用Proxy.newProxyInstance利用反射生成代理对象
        InvocationHandler invocationHandler = new ProxyHandler(hello);

        //通过Proxy类的静态方法newProxyInstance返回一个接口的代理实例(注,这里需要强转)。针对不同的代理类,传入相应的代理程序控制器InvocationHandler。
        //newProxyInstance需传入三个参数:分别传入被代理对象的classloader、interface,和创建的invocationHandler,
        HelloInterface proxyHello = (HelloInterface) Proxy.newProxyInstance(hello.getClass().getClassLoader(), hello.getClass().getInterfaces(), invocationHandler);
        proxyHello.sayHello(); //通过调用代理接口的方法,调用到了invocationHandler的invoke方法,从而调用到了被代理对象的方法
    }

调用结果:


动态代理比静态代理优秀的方法在于,可以动态地代理各个被代理类,那么此时新的代理类就来了。

创建新的代理类Bye:

public interface ByeInterface {
    void sayBye();
}
class Bye implements ByeInterface {
    @Override
    public void sayBye() {
        System.out.println("这里是被代理类Bye");
    }
}

重新执行:

    public static void main(String[] args) {
        HelloInterface hello = new Hello();  //创建需要被代理的Hello类对象
        ByeInterface bye = new Bye();

        //此时,不再创建具体的代理对象,而是用Proxy.newProxyInstance利用反射生成代理对象
        InvocationHandler invocationHandler = new ProxyHandler(hello);
        InvocationHandler byeHandler = new ProxyHandler(bye);

        //通过Proxy类的静态方法newProxyInstance返回一个接口的代理实例(注,这里需要强转)。针对不同的代理类,传入相应的代理程序控制器InvocationHandler。
        //newProxyInstance需传入三个参数:分别传入被代理对象的classloader、interface,和创建的invocationHandler,
        HelloInterface proxyHello = (HelloInterface) Proxy.newProxyInstance(hello.getClass().getClassLoader(), hello.getClass().getInterfaces(), invocationHandler);
        proxyHello.sayHello(); //通过调用代理接口的方法,调用到了invocationHandler的invoke方法,从而调用到了被代理对象的方法

        ByeInterface proxyBye = (ByeInterface) Proxy.newProxyInstance(bye.getClass().getClassLoader(), bye.getClass().getInterfaces(), byeHandler);
        proxyBye.sayBye();
    }

执行结果:


动态代理具体步骤:

通过实现 InvocationHandler 接口创建自己的调用处理器;
通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。

相关文章

  • 动态代理

    动态代理理论及Mybatis实战动态代理在我们平时编程并不常用,但因为Spring AOP以及大量框架均使用动态代...

  • 动态代理实战

    动态代理它可以直接给某一个目标(被代理 对象)对象(实现了某个或者某些接口)生成一个代理对象,而不需要代理类存在。...

  • Java动态代理-实战

    只要是写Java的,动态代理就一个必须掌握的知识点,当然刚开始接触的时候,理解的肯定比较浅,渐渐的会深入一些,这篇...

  • 面试系列~动态代理实现与原理

    动态代理有JDK动态代理, CGLIB动态代理, SpringAOP动态代理 一,JDK动态代理  jdk动态代理...

  • 编程常用的设计模式

    动态代理和静态代理 静态代理 动态代理 静态代理与动态代理的区别 JDK中的动态代理和CGLIB 实现动态代理的方...

  • Spring的AOP原理分析

    一 动态代理 动态代理分为JDK动态代理和CGLIB动态代理 jdk动态代理 被代理类(目标类)和代理类必须实现同...

  • 设计模式之代理模式

    代理分为静态代理和动态代理。 动态代理又包括基于JDK的动态代理、基于CGlib 的动态代理、基于Aspectj实...

  • Java高级主题(五)——动态代理

    代理可以分为静态代理、动态代理,动态代理又可以分为 jvm的动态代理 和 cglib的动态代理。像spring框架...

  • 动态代理

    动态代理分为两类:1、基于接口的动态代理; (JDK动态代理 )2、基于类的动态代理;(cglib动态代理)3、J...

  • 动态代理的两种方式

    静态代理就不说了,基本用到的都是动态代理。 Java中动态代理有JDK动态代理和CGLIB动态代理。 JDK代理的...

网友评论

    本文标题:动态代理实战

    本文链接:https://www.haomeiwen.com/subject/pejtultx.html