一个工作了五年的家务程序员去应聘德务 app 的月薪三十 k 的家务开发岗位,被一个基础问题问的措手不及,这个问题是什么呢?他是 gdk 动态代理,为什么只能代理有接口的类?这个问题啊,在他的认知里面是一个很正常的事情,竟然还有为什么? 好吧,对于这个问题,我们来看看普通人和高手的回答。普通人的回答,嗯,呃,因为 gtk 里面的动态代理类啊,然后他是默认会继承一个叫 proxy 这样一个类,呃,所以,因为加号里面他只能去实现单一继承嘛,所以,嗯,就是如果我我,所以我们只能去针对一项那个接口来做动态代理啊,因为,呃,对高速的回答,嗯,我认为这个问题的核心 本质啊,是 gdk 动态代理本身的机制来决定的。首先呢,在家务里面啊,动态代理是通过 proxy 点六 proxy instance 这个方法来实现的,它需要传入被动态代理的一个接口类。 之所以要传入接口而不能传入内啊,还是取决于 gdk 动态代理的一个底层实现。 gdk 动态代理呢,会在程序的运行期间啊,去动态生成一个代理类,叫 bolo proxy, 那么这个动态生成的代理类呢,会去继承一个加瓦点浪点 reflective proxy 这样一个类, 同时还会去实现被代理类的接口。在家务里面呢,是不支持多种继承的,而每个动态代理类都继承了一个 process, 所以就导致的 gdk 里面的动态代理只能代理接口而不能代理实现类。我之前啊去分析过动态代理的原码,发现啊, proxy 这个类呢,只是保存了动态代理的一个处理器,叫 emokit hunter, 如果不抽出来直接设置到多了 party 这个动态,这里的里面我认为也是可以的,如果这么去实现的话呢,就可以针对实现类来做动态代理了。作者为什么这么设计,我认为呢,还是有几个方面的原因。第一个是动态代理本身的使用场景 或者需求呢,只是对原始实现的一个拦截,然后去做一些功能的增强或者扩展,而实际的开发模式都是基于面向接口来开发的,所以基于接口来实现通来代理,从需求和场景呢,我认为都是吻合的,当然确实可能会存在一些 没有实现接口的一些类,那么这个时候我们要去实现动态代理,那么 gdk 很显然是无法满足的。第二个在家务里面,类的技能关系的设计啊,更多的是考虑到共性能力的抽象,从而去提高代码的重用性和扩展性。而动态代理呢,其实也在做这样一个事情,他封装了 动态代理类的深层的抽象逻辑,以及判断一个类是否是动态代理类,以及 evocation handle 的一个持有等等。那么我们去把这些抽象的公共逻辑放在 procas 这个负类里面,很显然也是一个比较正常的一个设计思路。 所以总的来说呢,我认为这个设计上并没有什么值得特别去讨论的地方,因为我认为技术的方案的设计是解决特定的场景问题的。如果一定要去针对普通类来去做动态代理, 我们可以选择 c 级赖卜这样的一个主见,他会动态生成一个被代理类的子类,子类重写负类的所有非法人里修饰的方法,在子类中去拦截负类的所有方法的调用,从而去实现动态代理。以上呢,就是我对这个问题的理解, 我看到评论区啊,有些小伙伴说面试问这些问题没有任何意义。我作为一个工作的十四年,做过开发价 购的程序员,最大的感受是越往上走啊,对于计算机的基础和底层的知识理解越来越重要。上层的框架可能会随着业务的发展而变化,但是底层的技术原理和设计理念是不会变化的,所以我认为掌握了基础, 能够以不变应对万变。从另外一个角度来说啊,大家都停留在业务框架的使用上,短期也许能带来较大的收益,但是随着生产工具的升级,比如人工智能、低代码、零代码、萨斯帕斯等逐步成熟和落地, 那业务程序员的价值会被逐步的弱化。这就像曾经的工业革命,工业革命之前的手工劳作,不管效率多高,技巧多么熟练,一旦由机器进行取代,那么传统手工劳动力必然会被淘汰,伴随而来的可能是技能的升级,从传统手工劳作转向了面向 机器的操作。所以呢,我认为底层逻辑啊,还是对一个事物的本质上的一个认识,而不是停留在表面上。好的,本期的普通人 vs 高手的面试系列的视频就要到结束了,喜欢的朋友记得点赞和收藏,我是 mike, 咱们下期再见!
粉丝15.7万获赞87.8万

今天我们来讲一下阿迪尔这个变异报错的问题,主要是这个 g d k 版本的问题。首先我们来看一下,就是执行的时候,然后报的这个变异错误,就是这个 g d k 版本不对,然后怎么解决呢? 主要是这里要设置一下这个版本,这个版本是有问题的,不对的点到这里来,然后就可以看到这个加瓦这个变音器,这里这里这里这个版本是是七,然后把它改到八就可以了。 点应用我们再来试一下。好,现在可以就是变音通过,而且也执行成功了。最后我们来总结一下,就是除了刚才那个地方,可能是那个地方的那个解决一百分之问题,还有 另外一个地方就是右键项目,然后点这个 oppo 模块设置,然后找到这个模块,这里这里也有这个 gdk 版本,也有可能是这里有问题。 然后还有一个是这个项目,这里这个是这个版本,然后这个是这个版本,如果是出现这个阿迪尔里面,然后出现这个就这个版本的问题,就是这几个地方,看一下是不是你想要的那个版本,基本上就可以解决这个问题了。好,谢谢。

今天我们一起首撸一下 gdk 的动态代理,首撸一个代理的核心,我觉得主要是上面三点,接下来我们一起写一下看看。 首先呢实现一个被代理的接口,我们简单实现一个方法吧,如撞图做事,然后呢去实现这个接口,内容如上图,这里我们的第一步工作就做完了,接下来我们去实现我们的代理接口方法, 这里需要去继承实现这个借口。然后呢这里就是我们代理方法要做的事情,我们主要的发挥空间就在这里,这里我就用简单的输出来代表我们做的事, 实际上这里可以做很多很多的扩展功能啊,现在还少一个构造方法,我们创建一下,接下来就是 去实现对应的关关系的绑定,当然这只是比较通俗的理解哦,接下来我们就来测试一下我们对应的代理,我们看一下输出的结果是什么呢? 可以看到就是代理方法之前我们做的一些动作,你还有什么问题吗?欢迎留言。

本次分享会分别介绍 jdk 及 cgab 动态代理的实现原理,并通过实力代码向大家演示如何在项目中使用,他们最后会总结二者的特点以及相互间的区别。在这之前,我们先回顾一下什么是代理模式。 代理模式就是给某一个对象提供一个代理,并由代理对象控制原对象的引用。代理对象在客户端和目标对象之间起到中介作用。图中是代理模式的通用类图,概念比较抽象。我们举个例子,假设你要去吃饭, 你可以选择自己在家做饭,然后吃饭,最后刷碗,所有的事情呢都自己做,也可以选择去餐厅,自己只管吃饭,把做饭和刷碗的活都交给代理对象,也就是 餐厅的工作人员类。图中 subject 就是定义吃饭行为的接口, real subject 就是你自己, proxy 可就是代理。我们先来看一下 j d k 的动态代理,主要包含以下几个重要角色。我们知道 j d k 的动态代理的机制, 只能代理实现了接口的类,所以必须要先定义一个接口,然后接口中定义被代理对象要实现的方法。再者就是 proxy 类,调用 proxy new proxy instance 方法之后, 可以产生一个 proxy 类的实力及代理对象。代理类的实力都需要关联一个 handler, 当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由 invocation handler 这个接口的 invoke 方法来进行调用。 invoke 方法一共接受三个参数, proxy 就是 j d k 动态生成的最终代理对象。 method 就是我们所要调用真实对象的某个方法的 method。 对象 arx 表示的是调用真实对象某个方法时接受的参数。接下来我们通过一段演示代码 来加强一下对 jdk 动态代理的理解,这里方便起见,把所有的接口和类都写到了一个文件中, 实际开发还是要做好区分。代码与先前的类图和例子作对应。首先定义一个接口, subject 接口中只定义了一个方法,即吃饭。接着是一个实现类,也就是要去吃饭的自己的实力。 it 方法实现中就输出了一句话,自己只管吃饭。再接着 呢,就是要让代理类帮我们做饭刷碗。前面提到代理类的实力都需要关联了一个 handler 原有方法,最终通过 handler 的 invoke 方法来调用。 重写 invok 方法时会调用原有对象 target, 也就是 yourself 实力的方法,同时可以把做饭刷碗的事情加进去。这里我们也是只做了简单的输出, 做饭,自己吃饭刷碗。最后是通过代理调用增强后的方法。代理的创建 new proxy instance 需要三个参数,分别是目标对象的类加载器, 目标对象的实线接口以及关联的 handler。 main 方法中也就是整个实现的主流程,创建对象创建 handler, 创建代理类调用增 增强方法。最后运行一下自己吃饭,餐厅干活一切正常。以上就是 j d k 动态代理的分享, c g leap 静待下期。



哈喽,大家好,我是坚持用专业为程序员赋能的灰灰。 my babies 跟 three 里面的 a o p 是程序员必须要掌握的核心知识,而在学习这两个知识点之前,我们要先了解一下什么是共同代理, 所谓的动态代理啊,关键思想呢,在于拦截我会去生成一个新的对象来拦截之前对象的方法。所以啊,关键步骤呢,有以下几步,第一,我基于想被拦截的对象生成一个代理对象,第二,要用代理对象的方法进行拦截。 动态代理的实现方式啊,主要呢有两种,第一种呢就是 gdk 的动态代理,还有一种是 cg 内部的动态代理。那我们今天就先来了解一下 gdk 的动态代理。 另外,为了帮助大家合理的制定学习计划,我准备了一份加瓦程序员学习路线图,里面有小白清洁到架构式的完整学习路径,有需要的小伙伴可以在评论区置顶中 中免费领取。 gdk 的关键类是 box 类,我们来看几个重要的步骤,第一步,基于被代理对象生成一个代理对象,调用方法是 box 这个类的 new blocksy instance 方法里面会有三个参数,第一个生成的新的对象的类加载器,第二个被代理的接口集合 ktk 只能代理接口。第三个拦截器,它是一个 invoks handle 的接口,因为我们刚才讲了,动态代理的核心思想在于拦截拦截以后走到哪里就是进入我们传过去的,实现了 invoks handle 接口的 in work 方法。申请完代理对象之后,接下来就是去调用,我们先来举个例子, 内加载,我就用当前的 jk test 的内加载器。第二个参数是一个接口的速组,我们先去创建一个接口,这个接口是一个人类,人类里面它有一个方法返回的 这个 screen 去 find the boy 好,或者说 friend, 然后呢?有有参数,就是你去找谁把参数传过来,我们再把这个接口传入过去,它是一个数组,它可以传多个,用一个 class 的数组传入一个 air person, 这是第二个参数。然后接下来第三个参数,实现了一个 emoques handle 的接口,我们可以去 new 一个如果是 handleme 的接口,然后有一个 in book 方法,我们先打印出来, 我们去创建了一个代理对象,可以去进行接收。这个接收由于是基于一个接口,也就是我们的 app person 去创建的接口,那么你也可以用 app person 去接收, 进行一个长转,然后我去调用。你是一个接口吗?我去调用你的方法,比如说叫灰灰,我们去执行一下,你会发现我打印出了一一,也就是他走到了拦截器的一个方法, 你握个方法,那么这一个就是动态代理的思想。我去调用方法的时候,我先走到的是拦截器,当然这个 o 他其实是一个代理对象,而不再是原来的那一个接口了。我们可以第八个看一下, 你看他是一个 roxan 的对象,好,那么这个就是动态代理,动态代理以后我们来看他的实现逻辑是什么呢?我们可以基于这个代理对象去把它打印出来,我可以去掉用底层的一个方法 传几个东西,第一个你要打印到哪里,对吧?你的名字假如说叫 brooksy。 二、这里传的是一个数组,也就是 a person declass, 我们可以用牛,用牛去把它打印出来。现在我得到了代理对象的字典,叫 file output screen, 打印到哪里?出来一个地址, d 盘的 broxy r d class, 然后写到本地,把我们的牛 写出来。然后呢,把这关闭 boys close, 我们再去执行一下,让一下他会生成一个文件,就是在底盘下面一定会有个文件,有个 box。 二、我们来看一下这个代理对象,你会发现他是继承了我们的 boxe 关键类,这个类是我们刚刚去生成代理对象的。 然后呢,实现的接口,既然实现的接口,我会去实现它的方法, find the boyfriend, 然后它里面做了件事情,它返回的是 super 点 h, super 是我们的 brooksy, h 是我传进去的,因为我是 handled 呢 in work 方法,然后这些是参数, 实现了 invest hand 的接口的方法的参数。由于你是传进来的嘛,那么是不是就走到了我们的什么传进来的 invest handled in work 方法?总结一下, gdk 动态代理必须要通过接口去进行代理,因为代理对象要去实现相关的接口,然后实现方法 里面会去调用传进去的拦截器的 in work 方法,从而实现拦截。今天的内容就分享到这里,如果有什么不同的看法,或者想要咨询其他的问题,都可以在评论区留言,我是灰灰,我们下期再见。