动态代理是基于什么原理?

作者: 遛狗的程序员 | 来源:发表于2018-07-25 22:34 被阅读14次

问题:

动态代理是基于什么原理?

知识点:

  1. Java是静态的强类型语言,但是因为提供了类似反射等机制,也具备了部分动态类型的语言能力。
  2. 代理模式:
    定义:给某个对象提供一个代理对象,并由代理对象控制对于原对象的访问,即客户不直接操控原对象,而是通过代理对象间接地操控原对象。(类似在上海这边经常看到的房屋中介)
image

静态代理模式代码:

public class ProxyDemo {
    public static void main(String args[]){
        RealSubject subject = new RealSubject();
        Proxy p = new Proxy(subject);
        p.request();
    }
}

interface Subject{
    void request();
}

class RealSubject implements Subject{
    public void request(){
        System.out.println("request");
    }
}

class Proxy implements Subject{
    private Subject subject;
    public Proxy(Subject subject){
        this.subject = subject;
    }
    public void request(){
        System.out.println("PreProcess");
        subject.request();
        System.out.println("PostProcess");
    }
}


  1. 反射:
    Java 反射机制在程序运行时,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。这种 动态的获取信息 以及 动态调用对象的方法 的功能称为 java 的反射机制。
    反射机制很重要的一点就是“运行时”,其使得我们可以在程序运行时加载、探索以及使用编译期间完全未知的 .class 文件。换句话说,Java 程序可以加载一个运行时才得知名称的 .class 文件,然后获悉其完整构造,并生成其对象实体、或对其 fields(变量)设值、或调用其 methods(方法)。具体可以参考:Java 反射由浅入深 | 进阶必备

运行时注解利用反射会影响性能,编译时候注解不会影响性能。
通过注解方式声明订阅方法,速度相比2.x会变慢,通过引入注解处理器(annotation processor),在编译期间建立订阅方法的索引,性能有明显提升。

根据官方说明,注解的引入让EventBus 3.0相比2.x性能变差3-5倍,但是引入索引,3.0相比2.x性能提高至少3倍。

详细了解请参考:EventBus 3.0 最佳实践和原理浅析

  1. 动态代理:
    为其他对象提供一种代理以控制对这个对象的访问。某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以再两者之间起到中介作用。运行阶段才指定代理哪个对象。
    组成元素:
    • 抽象类接口
    • 被代理类(具体实现抽象类接口的类)
    • 动态代理类,实际调用被代理类的方法和属性

实现方式
- [x] JDK 自身提供的动态代理,就是主要利用了反射机制

//retrofit2.Retrofit源码中就使用到了
public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T)
    //划重点了
    Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            // If the method is a method from Object then defer to normal invocation.
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

其他实现方式:利用字节码操作机制,类似ASM、GGLB(基于ASM)、Javassist等

回答问题:

这里不作回答了,自己根据上面知识点进行总结吧。在APM功能开发的时候,动态代理使用场景及其广泛,以及在我们针对不同机型适配的时候,反射使用场景次数较多。

/**
     * 隐藏系统键盘
     */
    public void hintSystemSoftKeyboard() {
        if (getWindowToken() != null) {
            ((InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(getWindowToken(), 2);
        }
        if (Build.VERSION.SDK_INT >= 11) {
            try {
            //以下是本章重点内容,请仔细体会
                Class[] arrayOfClass = new Class[1];
                arrayOfClass[0] = Boolean.TYPE;
                Method localMethod = null;
                if (Build.VERSION.SDK_INT < 17) {
                    localMethod = EditText.class.getMethod("setSoftInputShownOnFocus", arrayOfClass);
                } else {
                    localMethod = EditText.class.getMethod("setShowSoftInputOnFocus", arrayOfClass);
                }
                localMethod.setAccessible(true);
                Object[] arrayOfObject = new Object[1];
                arrayOfObject[0] = Boolean.valueOf(false);
                localMethod.invoke(this, arrayOfObject);
                return;
            } catch (SecurityException localSecurityException) {
                localSecurityException.printStackTrace();
                return;
            } catch (NoSuchMethodException localNoSuchMethodException) {
                localNoSuchMethodException.printStackTrace();
                return;
            } catch (Exception localException) {
                localException.printStackTrace();
                return;
            }
        }
        setInputType(0);
    }

参考:

声明:此为原创,转载请联系作者


作者:微信公众号添加公众号-遛狗的程序员 ,或者可以扫描以下二维码关注相关技术文章。

qrcode_for_gh_1ba0785324d6_430.jpg

当然喜爱技术,乐于分享的你也可以可以添加作者微信号:

WXCD.jpeg

相关文章

  • Spring AOP 实现原理

    Spring AOP 实现原理 静态代理 众所周知 Spring 的 AOP 是基于动态代理实现的,谈到动态代理就...

  • 动态代理是基于什么原理?

    问题: 动态代理是基于什么原理? 知识点: Java是静态的强类型语言,但是因为提供了类似反射等机制,也具备了部分...

  • 动态代理-jdk代理实现原理

    动态代理-jdk代理实现原理 JDK中提供了一个Proxy类用于实现动态代理,JDK的动态代理是基于接口实现的,被...

  • java动态代理

    本文从四个方面认识动态代理 什么是代理? 为什么使用代理? 如何使用动态代理? 动态代理的原理 一 什么是代理 ...

  • Spring AOP内部调用失效问题

    Spring AOP基本原理 Spring AOP是基于动态代理机制实现的,通过动态代理机制生成目标对象的代理对象...

  • Java动态代理从入门到原理再到实战

    目录 前言 什么是动态代理,和静态代理有什么区别 Java动态代理的简单使用 Java动态代理的原理解读 动态代理...

  • 2020-05-25-问题解决-but was actually

    办法 改为 问题 问题原因 Aspect的实现原理是基于接口的动态代理技术,而不是基于实现类的动态代理技术 有一个...

  • Spring AOP(一)

    Spring AOP实现原理 动态代理: 利用核心类Proxy和接口InvocationHandler(基于代理模...

  • 设计模式之代理模式

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

  • Spring中AOP的特性解析

    要了解Spring的AOP就必须要了解动态代理的原理,因为AOP就是基于动态代理实现的。 java.lang....

网友评论

    本文标题:动态代理是基于什么原理?

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