zoukankan      html  css  js  c++  java
  • java 动态代理机制

    代理模式是Java中常用的设计模式,主要由公共接口、被代理类和代理类等三部分组成,代理类持有被代理类的实类,代为执行具体的类方法。其中代理类与被代理类有同样的接口。

    代理类的对象本身并不真正实现服务,而是通过调用被代理类对象的方法来提供特定的服务。

    代理分为静态代理和动态代理,编译时能确定被代理的类就是静态, 在运行过程中确定要被代理的类则是动态代理

    静态代理:

    public class daili_demo {
        public static void start(a a){
            a.echo();
        }
        public static void main(String[] args){
            daili_demo.start(new proxy_subject());
    
        }
    }
    
    interface a{
    
        void echo();
    
    }
    
    class real_subject implements a{
            public void echo(){
            System.out.println("real echo");
    
        }
            public static void test(){
                System.out.println("test");
            }
    }
    
    
    class proxy_subject implements a{
    
        public void echo(){
            System.out.println("start");
            new real_subject().echo();
            new real_subject().test();
            System.out.println("end");
        }
    }

    比如上面这段代码实际上proxy_subject和real_subject有相同的接口,proxy_subject即代理类,我们可以在其中调用被代理类的方法,也可以在代理类中实现自己的逻辑

    动态代理:

    在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。在程序运行过程中产生的这个对象,其实就是通过反射机制来生成的一个代理。

    每一个动态代理类都必须要实现InvocationHandler这个接口

    InvocationHandler:

     该接口只有一个方法invoke,动态代理类都必须实现该接口,那么也必须要实现该方法,入口参数Object proxy即为要被代理的对象,method为被调用的方法,args为参数

    Proxy类

      jdk说明中也说了一种简单的方式用于创建动态代理,通过调用Proxy.newProxyInstance函数,proxy类是支持序列化的

    import java.lang.reflect.Proxy;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    public class dongtaidaili_demo {
        public static void main(String[] args){
                read_object ppp =  new read_object();
                daili handler = new daili(ppp);
                b get_b = (b)Proxy.newProxyInstance(ppp.getClass().getClassLoader(),ppp.getClass().getInterfaces(),handler);
                get_b.fun1();
        }
    }
    
    interface b{
      public   void fun1();
      public   void fun2();
    
    }
    class read_object implements  b{
    
        public void fun1() {
            System.out.println("fun1");
        }
        public void fun2() {
            System.out.println("fun2");
        }
    
    }
    
    class daili implements InvocationHandler{
    
        private Object subject;
        daili(Object subject){
            this.subject = subject;
        }
        public Object invoke(Object object, Method method, Object[] args) throws Throwable {
            System.out.println("start");
            System.out.println(method);
            method.invoke(subject,args);
            System.out.println("end");
            return null;
    
        }
    }

    JDK会生成一个叫$Proxy0的代理类,这个类文件是放在内存中的,在创建代理类对象时,通过反射机制获得这个类的构造方法,然后创建代理类实例。

    所以整个创建动态代理的流程为首先要声明被代理的接口,然后声明所需要的代理类,然后创建动态代理类,该类要实现incationhandler接口,然后实现invoke方法,也就是具体的代理处理逻辑,并且要通过该

    类的构造方法将被代理的对象传进代理类,以便于在invoke函数中进行反射调用。实现代理与被代理的联系是通过newProxyNewinstance,此时要传入classloader,一组接口(就是想要被代理的),以及动态处理类,那么返回的也是一个接口,这个接口可以是一组接口中的任何一个,通过该接口来调用接口内的方法就能够触发动态代理类内部的invoke函数来实现,classloader是sun.misc.Launcher$AppClassLoader,所以最后可以得到jdk中动态代理实际上就是给接口做的代理

     为什么说是动态代理也就是程序运行时通过这三句才确定的代理与被代理的关系

    参考:

    https://www.mi1k7ea.com/2019/02/01/Java%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E6%9C%BA%E5%88%B6/

  • 相关阅读:
    对象遍历 for in ,数组遍历for in 与 for of 的区别
    计算一个数组中key值相同的数量
    VUE的两种跳转push和replace对比区别
    微信公众号二次分享ios分享失败问题
    获得对象中的键或值
    第一个table根据checkbox选择tr,在另一个table中显示对应索引的tr(jq遍历的运用)
    checkbox 全选反选 获得所有的checkbox
    为什么jQuery要return this.each()?
    用jq代码写出一个轮播图。
    页面滚动到一定位置,两个div 朝中间运动。
  • 原文地址:https://www.cnblogs.com/tr1ple/p/12260664.html
Copyright © 2011-2022 走看看