• 【Java基础】静态/动态代理


    一、反射: java.lang.reflect.*

    Class<?> birdClass = Class.forName("com.baeldung.reflection.Bird");
    Constructor<?> cons1 = birdClass.getConstructor();
    Constructor<?> cons2 = birdClass.getConstructor(String.class);
    Constructor<?> cons3 = birdClass.getConstructor(String.class, boolean.class);
    
    Bird bird1 = (Bird) cons1.newInstance();
    Bird bird2 = (Bird) cons2.newInstance("Weaver bird");
    Bird bird3 = (Bird) cons3.newInstance("dove", true);

    二、静态代理

          参考proxy设计模式实现,参考 https://www.baeldung.com/java-proxy-pattern

          缺点:需要实际编写代理实现类

           

    三、动态代理 JDK Proxy(仅基于接口)

     参考:https://www.baeldung.com/java-dynamic-proxies    https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Proxy.html

    Proxy provides static methods for creating dynamic proxy classes and instances, and it is also the superclass of all dynamic proxy classes created by those methods.

    • Dynamic proxies allow one single class with one single method to service multiple method calls to arbitrary classes with an arbitrary number of methods.
    • A dynamic proxy can be thought of as a kind of Facade, but one that can pretend to be an implementation of any interface. Under the cover, it routes all method invocations to a single handler – the invoke() method.
    •  dynamic proxies can be quite useful for framework writers. It may also be used in those cases where concrete class implementations won't be known until run-time.

    来自: JDK chm样例

    To create a proxy for some interface Foo

    InvocationHandler handler = new MyInvocationHandler(...);
    
    Class<?> proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), Foo.class);
    Foo f = (Foo) proxyClass.getConstructor(InvocationHandler.class).newInstance(handler);

    or more simply:

    Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
                                         new Class<?>[] { Foo.class },
                                         handler);

    上述关键方法:

    1、Class

            静态方法:Constructor<T>  getConstructor(Class<?>... parameterTypes): 根据顺序输入的参数类型,得到与之参数类型匹配的Constructor对象(因为可能constructor可能有多个)

            Returns a Constructor object that reflects the specified public constructor of the class represented by this Class object.
            The parameterTypes parameter is an array of Class objects that identify the constructor's formal parameter types, in declared order.

    2、Constructor类

          实例方法:Constructor<T>.newInstance(Object... initargs): 通过传入当前constructor对应的入参value,得到当前对象实例

      Uses the constructor represented by this Constructor object to create and initialize a new instance of the constructor's declaring class, with the specified initialization parameters.

    3、Proxy类:负责动态生成新的代理实现类

      

           newProxyInstance 方法定义:生成新的代理实现类            参数2:需要被代理实现的类;    参数3:新代理类的实现

          

     4、InvocationHandler接口:关键实现,负责代理部分自有逻辑 + 被代理实现的整合

         

            proxy:  所代理的那个真实对象

            method: 要调用真实对象的某个方法的Method对象

            args:  调用真实对象某个方法时接受的参数

          而接口实现类:通过构造函数,传入被代理的对象实例,从而可以在接口中调用被代理对象的同名方法实现。

          

           main函数: People 是接口,Proxy最终生成People接口的实现类;

       


     四、动态代理 CGLib

    实现思想是继承

    net.sf.cglib.proxy.Enhancer;
    net.sf.cglib.proxy.MethodInterceptor

    net.sf.cglib.proxy.InvocationHandler

    net.sf.cglib.proxy.MethodProxy;

    Cglib动态代理执行代理方法效率之所以比JDK的高是因为Cglib采用了FastClass机制
    它的原理简单来说就是:为代理类和被代理类各生成一个Class,这个Class会为代理类或被代理类的方法分配一个index(int类型)。
    index当做一个入参,FastClass就可以直接定位要调用的方法直接进行调用,这样省去了反射调用,所以调用效率比JDK动态代理通过反射调用高。

    1、方法级别代理

         

    2、类级别代理

        

  • 相关阅读:
    httpclient5:信任所有证书,调用公众号接口
    驾驶技能考试系统:常见故障原因分析及排除
    C#:Combox实现key,value
    C#:密码框的两种方式
    C#:动态添加或删除控件,并根据控件名称获得控件
    微服务设计模式
    微服务设计模式
    微服务设计模式
    微服务设计模式
    微服务设计模式
  • 原文地址:https://www.cnblogs.com/clarino/p/15157571.html
Copyright © 2020-2023  润新知