粉丝7.8万获赞28.6万

我们今天来学习下代理模式,他的定义呢是说由于某些原因需要给某对象呢提供一个代理,以控制该对象的一个访问。 之所以这么做呢,是因为访问对象啊,不适合,或者不能直接引用目标对象,代理对象呢,这个时候呢就可以作为访问对象与目标对象之间的一个中介来使用 啊,但从定义上来说呢,确实比较抽象啊,其实现实中呢这种场景呢也随处可见。你比如说我们租房为例,我们通常租房的时候呢,房子呢是房东的一个,但是呢房东呢可能由于啊他不想麻烦,或者说呢他不想暴露自己的一个隐私, 所以说呢他会代理呢,这个中介公司对我们出租这个房子,这个呢就是一个典型的一个代理模式。还有呢,比如说啊,有一款外国的游戏啊,他通常很火的时候呢, 国内公司呢会通过买他的一个版权呢,然后呢在这个国内呢代理他的游戏,这呢也是一种代理,你比如说他代理这个游戏的时候呢,他通常呢可以在这个游戏的原有的功能基础上呢,好来扩充一下他自己的一些功能 啊,这个呢也是代理模式的一个典型的场景,下面我们看一下啊代理模式的一个几个主要角色,他呢总共有三个角色,第一个角色呢就是主体,第二个角色呢就是一个真实主体角色。第三呢就是一个代理角色 啊,主体角色呢,其实他就是一个接口啊,他呢为了就是让这个真实主体与这个代理角色呢有一个统一的一个方法,有一个相同的方法,所以说呢,嗯,真实主体角色和代理角色呢,会实现这个主体角色来重写他这 这个方法。然后呢代理角色呢会在内部呢对这个真实主体角色做一个引用,来调用这个真实主体的重写这个方法。下面呢,我们来结合一个具体的一个失利吧,来详细的看一下这个代理模式。首先我们来看一下我们要写的这个例子的一个类图, 首先我定义了一个 game 游戏的一个接口,在这个接口里面呢,我定义了一个 play 的一个方法,也就是玩游戏的方法。接下来呢,我定义了一个游戏类啊,这个游戏呢叫做魂斗罗游戏,这个游戏呢是陪伴我长大的一个经典游戏啊,小的时候非常喜欢玩 他呢,实现了这个 game 的游戏接口,来重写他这个破类方法啊。最后呢又定义了一个魂斗罗游戏的一个代理类通来代理这个魂斗罗游戏 啊,然后呢他这里边聚合了一个魂斗罗这个一个对象,然后呢通过也是重写了一个普雷方法。最后呢为了对这个普雷游戏呢做一个扩充功能的一个扩充,我又定义了两个方法,一个是普瑞普雷,一个是阿特普雷。下面呢我们就依据啊这个类图来详细的写一下他的代码。 首先我定义一个接口也叫 game, 然后呢在这里呢,我定义一个盆类方法, 这个角色呢,他其实就是啊主体角色。 接下来呢,我再定一个魂斗罗游戏类, ctrl, 然后呢实现这个 game, 重写了他这个 play 啊,做一个打印吧, 魂斗罗游戏开始,比如说, 然后呢我再定义一个魂斗罗的代理类很臭 proxy, 同样呢他也是实现这个啊 game 重写他这个不累方法。然后呢这个角色呢,他就是一个代理角色,代理角色 这个就是一个真实角色,真实的一个主体角色,真实主体角色, 然后我们刚才说了,在这个代理角色里呢,我会对这个主真实主体角色呢做一个聚合引用,同时呢就这个 ctrl 做一个这个东西引用,然后呢我会在这个代理角色这个普雷方法里面调用这个啊 ctrl 的一个普雷方法,这样就能就达到代理角色呢调用这个真实主体角色的一个方法。然后呢这个 ctrl 我们没有处置化,所以有没有在在这个构造函数里呢对他做一个处置化。 接下来我们定义两个私有的方法,对这个代理的盆类方法呢做一个功能的扩充。第一个方法 tv pre play, 然后打印一下 魂斗罗游戏开始前。 第二个方法呢是 private void 啊,这个 after play, 也就是游戏这个结束后,然后呢打印一个魂斗罗 游戏结束后,然后呢我们在这个普雷方法里啊,在调用这个 ctrl 普类方法之前呢,我们先调用这个这点普瑞普雷, 在这个调用这个 ctrl pro plate 之后呢,我们再调用一下这个 ft play, 这样的话呢,我们代理这个方法呢就对了,这个 ctrl 的游戏呢,做了两个扩充,所以当我们运运行他的时候呢,他就会先打印这个魂斗罗游戏开始前,然后呢接着会打印这个魂斗罗游戏开始,最后呢他会打印这个魂斗罗游戏的这个结束后, 这样的话呢我们看一下,我们建一个闷方法啊,建一个 app 类吧,然后闷闷方法,这样的话我们就可以对这个 ctrl 呢做一个扭,然后声明他的一个代理类, 最后呢我们就可以通过这个代理类啊来调用他的婆类, 你们运下来看看, 我们看到这个魂斗罗游戏开始他已经打印出来了,也就说明通过代理类呢,我们就实现了这个呃真实主体角色,魂斗罗游戏的一个调用, 这样呢我们的一个代理设计模式啊就已经写完了,他其实啊就是一个普通代理,普通代理呢,他呀就是通过这个代理访问角色啊,然后呢不能直接访问这个真实角色,真实角色呢出手画呢放在这个代理的一种, 也就是说我们刚才看到的这个代理角色里呢,他有一个真实角色这么一个引用,然后通过这个呢构造函数呢把它处置化,然后呢再通过这个代理这个破裂方法呢调用他这个真实角色一个普通方法来达到代理这个真实角色的一个目的。 但是我们发现我们现在代码有个问题,我们说这个不能直接访问这个真实角色,但是我们看啊发现我们现在是可以访问他真实角色的, 我们直接调用这个 ctrl 点 play 呢,也是可以运行的。我发我们执行一下,我们发现他也打印了这个混动流游戏开始,而且呢他又没有这个代理类这个扩充功能, 所以说呢这种呢对我们来说呢,有的时候呢他是不允许的,是必须要求他通过代理类来访问的,也就是我们这种强制代理,强制代理呢就是在真实角色处罚后呢不能直接使用,必须通过这个代理类来获取 啊,来调用他对应的方法。强制代理呢,我们通常呢增加一个这个 get proc 这么一个方法来实现, 具体怎么实现呢?其实有很多方式啊,我们来简单说一下一种方式,首先呢我们改造这个真实角色,我们在他这里呢加一个 get process, 我们上面一个静态方法,然后呢我们返回一直呢是一个嗯这个魂斗罗 pro c 对象 盖的 proxy, 我们在这个方法里呢,你有一个魂斗罗真实角色的一个对象, 等于扭一个 ctrl, 然后呢我们返回这个代理角色的一个对象,扭一个 concorproxy, 然后呢把这 ctrl 呢传进来,这样的话呢我们通过这个 get process 呢,他就获得了这个代理角色, 然后为了呢让我们这个啊真实角色呢不能在外部被调用,我们给他写一个私有的啊,一个这个构造函数, 这样的话呢我们 在外边呢就不能说实话他了,然后只能通过这个 get plus 呢去调用获取这个代理对象来调用他的破裂方法,所以说我们看这里我们这块呢就报错了,我们就需要改造一下,把这个就直接删掉, 我们直接通过 ctrl 他的静态类 get proc 来获取他的一个代理对象 啊,改一下名叫 ctrl plus, 然后呢这样的话我们就直接调用这个 ctrl plusc 点 play, 这样呢就实现了他的一个强制调用这个代理方法,这样呢我们就可以嗯得到这个扩展的一个功能,因为我们无法获取到了这个 ctrl 对象,所以呢我们就不能通过这个 ctrl 对象来调用他这个分类方法了。这样呢,我们就达到了 这个强制代理的这么一个作用啊,就像我们刚才看到的一样啊,代理模式呢,可以在不修改被代理对象的基础上呢,通过扩展代理类 啊附加功能的一个增强,就像我们刚才我们在这个代理类里呢增加了一个普瑞和一个阿富特普瑞,然后呢对这个普瑞呢这个方法呢做了一个增强。 带累累和被带累累呢,应该共同实现一个借口啊,或者是共同继承某个累。我们这里呢他都共同实现了一个 game 接口来重写他的一个破累方法。 通过上面我们写的一些简单的视力代码呢,我们就完成了一个代理模式。然后呢他呢代理模式呢,他主要有几个优点啊 啊,代理模式就是在客户端有目标对象之间呢,起到了一个中介作用,保护目标对象,有时候我们无法直接 直接调用这个目标对象啊,就可以躲过他的一个隐私啊。代理对象呢可以扩展目标对象的一个功能,也就是我们刚才实现了这个普瑞和这个 after 来扩展他的功能。 代理模式呢,能将客户端与目标对象分离,在一定程度上呢降低了系统的偶和度。

加瓦成学员一定要知道面向切面编程的原理,也就是 aop 编程的原理,今天我就来讲一下,这个内容比较长,记得点赞收藏好。首先我们来看一下基本概念,什么是 aop 编程,他呢叫做面向切面编程,是一种编程思想, 这个在语言上呢不太好描述,但是它作用主要是可以提高代码的复用性,可以解偶,方便代码维护,等会我们看代码的时候你就理解了。然后我们再来看一下动态代理, aop 编程的原理呢,就是动态代理,通过动态代理去实现的,那么什么是动态代理呢?简单的说就是这样的,假如说我们原来有个对象,然后里面有一些方法,代理的意思就是 原来的对象创建一个代理对象,我们通过这个代理对象去调用原对象里面的方法, 那么动态的意思呢?他指的是这个代理对象呢,是在代码执行过程中,通过反射技术动态创建出来的。好,这就是基本概念。接下来我们上代码,首先呢我有这么一个接口叫 dog, 里面有两个方法,一个叫阴分,一个叫 run, 然后呢我有一个实现类叫旺财,然后呢他实现了阴分方法打印出,我叫旺财,然后呢还有一个 run 方法打印出,我跑的很快。 好,那么接下来我有一个需求,就是说我要在 这个音份方法执行前和执行后加一对逻辑,在 run 方法执行前和执行后也加一对逻辑。 那么呢我创建了一个工具类,里面有两个方法,买油条工具类里面有两个方法,一个叫 before, 一个叫 after, before 就打印出 before, after 就打印出 after, 那么我的这个需求就是我在 执行这个引粉方法的时候和 run 方法的时候,你都执行前,你先给我执行一下这个 before 方法,执行完以后你再给我执行一下这个 offer 方法。那么如果我们用传统的方法来做的话,那么你肯定是在这,对吧?加一个卖油条 点,然后呢在后面加 my youtube 点 after, 那么如果我们传统的方法肯定是这样来做的,对吧?下面这个也一样啊,我就不写了, 那么这样的时候他也是没问题的,但是呢,如果我方法很多,对吧?你每个方法都要写这个买油条的 before, 买油条的 after, 并且呢他与我们这个银粉方法本身已经呕合在一起了,那么现在我们有没有一种办法,就是说 我不在这里钓,同样也能满足我这个需求呢,那么这个就用到了动态代理。好,接下来我们看一下如何创建他的代理对象。那么创建佳话,创建代理对对象呢?我用到了两个累, 一个呢是这个 proxile 是在反射包下的,还有一个呢是一个接口 in vacation hander, 用了这个接口。 好,那我们就看一下是如何创建动动态创建这个代理对象的。我这里呢有一个方法,通过这个方法呢,就可以动态的创建出代理对象, 那么我这个方法参数呢,是一个 object 类型的,也就是说他可以为任何对象来创建代理对象,是一个比较通用的方法。好,我们直接来看最后一行, 我们的 proxy 类呢,有一个静态方法叫 new proxy instance, 通过这个方法呢,就可以直接创建出我们的代理对象,那么呢它有三个参数,一个呢是 classloader 类加载器,那么我们通过调动 target get class 点 get class low 的人就可以获得到,然后呢第二个参数是 interface, 他是个数组啊,那这个他是个什么意思呢?我来给你解释一下,假如说我们要创建旺财对象的代理对象, 那你首先你得有一个实现类啊,对吧?他实现了 bug, 那你现在要创建一个代理对象,你也需要有一个实现类,那么呢 他这个 interface 呢,指的就是说你这个实现类要去实现哪些接口,你要他传进来,那么我们这里旺财通过这个卡力的 get class, 第二 get interfaces, 对于旺财来说,那就他获取到的这个接口呢?就是到 那这样的话,我才知道如何去创建实现类,去实现哪些方法,对吧?就是这个意思啊,那我们一个类有可能会实现多个接口,所以说他这是一个数组的形式啊。好重点,第三个参数, 第三个词呢,他穿的是一个 invocation hunter, 看到了吗?他穿的是 invocation hunter, 他是一个接口啊,我们需要来实现这个接口,他有什么用呢? 我来说一下,其实你代理对象在调用方法的时候呢,他是通过这个英文 kishing handle 来进行调用的,需要你自己去实现一下啊。好,所以说我的第一行呢,我就自己实现了一下那个英文 kish 接口,我们来看一下里面是什么东西啊?买英文开始韩子,好,看见了吗?我实现了这个英文开始韩子这个接口,然后呢我里面有一个成员变量, 叫他给他,他那就是被代理对象,就是说你要给谁创建代理对象,你要传进来啊,你要告诉我给谁创创建代理对象,对吧?我通过构造方法给他附上值, 然后它里面有一个方法叫 invok, 那么你再通过代理对象去调用 a 代理对象的方法手,他其实呢就是调动了这个 in vacation handler 里面这个 in book 方法啊,他有三个参数,一个是 proxy, 就是我们的代理对象,就是生成代理对象啊, 然后 mest, 它代表我们的方法,你可以这么理解,然后呢阿格,阿格子,它呢就是我们方法的参数,就是我们类里面方法的参数。在这呢 我们就可以把这个买油条的 before 和买油条的 after 进行调用了,然后我们中间这行的代码呢, 他就是通过反射来调养我们原对象的方法,原对象就是我们背带对象的方法,也就是传进来这个他给他,你要给谁传进来的对象,对吧? 你穿进来以后在这呢进行调用 nice 点音 look, 然后呢把这个你要调用谁的方法就把它传进来,这是反射的内容啊,然后呢这是方法的参数,那么这样我们是不是就实现了我们刚才 的需求?在我们执行旺财的音份方法和 run 方法之前和之后,他都会加上这个 before 和 after, 这样是不是我们的偶合性就非常低了,并且我们的这个代码附用性也非常高?好,接下来我们来执行一下, 我现在呢就调用我这个 get proxy object 方法,就是这个方法,然后呢把我的目标对象传进来,也就是说你要给谁去创建代理对象?我这是旺财,对吧?然后他得到是一个 object, 然后呢,他其实 也是 dog 的一个实现类来创建了一个对象啊,就这个代理对象呢,他所处的类型其实也是 dog 啊,他是 dog 的一个实现类, 不过他是动弹传染出来的,你看不到我们,所以我们可以把它强转成动了,然后我调用 run 和音分方法,我们来执行一下, 看到了吗?我先调了 run 方法,然后呢,他会先执行 before 方法,然后呢再执行我的 run 方法,再执行 after 方法,然后我又调用了 in for 方法,他也会执行 before 方法,然后呢 执行我们的音分方法,然后呢完了再执行我们的啊分方法。这个呢就是动态代理, 也就是 aop 的原理。假如说我们现在又来了一个小黑,对吧?我也实现了我们的倒个接口,它里面也有这么两个方法,那么我们在这里只要你有一个小黑进来,就可以得到小黑的 代理对象,然后再调用他的方法时候,他就可以把我们的别夫尔阿福特也加上了,随着他的这个副用性是很高的啊。

一个工作了五年的家务程序员去应聘德务 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, 咱们下期再见!

动态代理有四种实现方案,那下面我们看一下用 cd 代步如何实现动态代理?那我们打开代码,首先我们有一个接口,这个接口里边呢有两个方法,这两个方法没有实现, 那么接下来我们有一个实线类,这个实线类的实现这个接口,然后覆盖这个接口里面的两个方法 好。然后第三个类呢,就是我们的一个 target properties 这个类,这个类呢它实现一个 measured intercept 这个接口, 那么这个接口呢,是我们 c g 内部里面提供的一个接口,我们可以看一下这个包导入是 c g 内部。好,那么这个类里面呢,首先第一个方法就是一个 get perforce 这个方法,那么这个方法呢,就是用来拿到一个呢代理论代 理对象通过这个方法里面传一个 class, 这个 class 呢可以是传个接口,也可以是传一个,真正的这个实现类都是可以的。那么 cg 内部它既支持对接口的动态代理,又支持对普通类的一个动态代理。 那么这里面这个方法的实现呢,就是基本上固定的这几行代码,我们有一个增强类,然后给增强类里面呢,你可以设置一个副类, 那么设置副类的话,表示你是基于这个对普通类的动态代理,那么你也可以设置一个接口,那表示你对接口的一个动态代理。 好,下面设置一个回调,回调是这一时,就是当前这个类,为什么是这一时呢?因为当前我们这个类啊,我们是实现了这个接口的,那么实现这个 接口,这个接口里面是有个方法的,我们到时要回掉这个接口里面,这个方法好,那就是它设置 this。 好,然后通过这个可以的创建就拿到了一个代理对象。 好,那么这个方法就看完了,然后下面这个方法就是呢他的一套 sopl 拦截方法,这个拦截方法到时会被调用好,在这个方法里边我们可以对目标类的 功能进行一个扩展和增强,比如说这行代码是调用目标类的方法,那么前面和后边呢,是我们自己扩展的这个功能, 所以他可以对我们目标方法进行拦截,然后在这个基础上进行功能的扩展和增强。好,那么这个类就 写完了。那接下来第三个呢,就是我们去测试啊,测试首先另一个我们这个啊,他给的 purpose 这个类,然后呢通过他来 get 到这个 purpose 这个方法,让传一个接口。 好,那么现在传个接口的话,表示我们对接口进行动的代理好,拿了这个代理对象,然后调接口的 say hello 和 say sunk 是两个方法。先找一片代码,看一下他有没有错误,或者他是是否可以成功运行,那么这个是他报错了,他说没有这个方法 好,那是因为呢?我们在获取动态代理对象的时候,我们这个地方设置接口,设置接口,那下面我们这个实现啊,南极的时候,南极的时候我们在这地方调用目标啊接口的一个方法的时候, 我们这个接口没有实现,所以这个时候我们不能这样调,我们要对接口进行代理的话,那这个时候呢,我们是没有时间类,对吧?那么这个时候我们需要自己手动实现一下。 好,那就说你在这里面去实现那个接口。好,那就是我们在这里可以写上我们的逻辑,比如说我去实现,我们去实现啊。好,我们虽然随便写个一一啊,简单一点,写一一,那么这地方我们返回个绕就行了。好,这表示我们自己去实现那个接口的这个方法。 好,那我们跑一下,那么现在他就可以运营成功了。 好,这是可以跑的,那么这是,呃,这个方法执行之前,方法执行之后,中间是那个接口的一个实现,那么这个接口实现是我们自己实实现的啊。好,这是这种方式 用接口啊,对接口的代理,那另外一种方式就是我们对一个普通类的代理,那就是对我们的时间类代理,比如说我们时间类,那么这个手边传一个来 mpl, 这个时间内传进来,然后我们就需要在这个类里面呢,我们要改一下,这地方就不是设置接口了,要设置一个呢,他的负类 相对是继承他这个类啊,然后对他进行拦截,好,设置副类。好,那么这个改好之后呢,我们下面这个拦截方法里面,就是我们不需要自己去实现了,因为他的实现类他是自己有实现的,他这个普通类他有实现,那么直接掉那个类就行了 啊,然后在前面进行增强,在后面进行增强。好,那么这个他的结果我们在淋水吞一下,对吧?好,那么代码写好了,我们这个是跑一下,那么这个是对我们的一个内的一个增强,不是接口,这个是是内。 好,跑一下,这是我们的方法,之前方法之后,这是目标方法的执行 啊。之前之后目标方法执行。好,这是我们 cg 内部实现动态代理,它既可以对接口进行动态代理,又可以对我们的普通的类进行动态代理。

springlp 的两种动态代理方式? jdk 动态代理通过反射实现一个代理接口的匿名类,主要是通过 proxy 和 invok 先看到的事情,针对实现了接口的内生成代理,当并实现接口时, spring 会采用 jdk 的动态代理 cgl 不同的代理通过先把增强技术动态的创建代理对象,如果目标对象没有实现接口, supreme 会采用 cglf 的代理。每日一问, supremelp 有哪些应用场景。

spring aop 他是在哪里创建的动态代理? spring aop 的这个动态代理他是在底层的哪个地方实现的?那这个 aop 的动态代理呢?他在两个地方等于创建一个地方呢?就是在病的生命周期的这个初始化之后, 会通过病的后置处理器的这个 host process after english leaders 创建 aop 的动态代理。当然这个你不需要记,这么你不需要完全说我把这些方法都记住,没有必要,对吧?你只需要记住它在病的生命周期的初始化之后,会通过病的后置处理器来进行创建 aop 的动态代理。 我们来看一下,好吧,关注无评,我通过代码呢给你们来看一下。对了,本视频的文档我已经整理好了,并且与往期内容一起汇总成了二零二三年最新家管面试文档,放在了视频的最后面,坚持看完一定对你有帮助。来找到这个病的后置处理器的这个接口, 那么我们可以看到呀,这个是初始化之前会调用的,这个呢,是初始化之后,那么他其实就是在初始化之后去调用的这个方法。我们来点一他的实线,那么你们觉得是哪一个实线类去创建的这个动态代理啊? 知名实意对不对?你看第二个就知道,肯定是这个,对吧?抽象的动态代理创建者,我们点进来, ok, 他在这里呢,会调用一个 whopper if necessary, 也就是说呢,如果有必要就给你创建东东代理。什么是有必要呢?也就是说呢,他会根据你配置的这个切点表达式来进行匹配,如果匹配上了呢, 他这里就会返回一个是否创建中代理,那么如果是要需要创建的话,他就会走这个衣服里面, 也就说呢,他在这个方法当中呢,会进行切点表达式的匹配,好吧,当然这个要用链也非常的深,我就不带着同学们具体的去看了。然后呢,如果切点表达式匹配上了,他就会走这个衣服里面,然后呢执行这个 crit proxy, 然后呢再执行下面的这个 ai 的 proxy, 我们来看一下,你看啊,他在这里呢就会有两个创建 l p 动态代理的实现类,一个呢 c 级 lab l p proxy, 一个呢 j d k dynamic 动态代理的 l p proxy, 所以说从这里我们就可以看出来,对吧?他会将他就会根据你的对应的一个实现呢进行动态代理的实现,那么我们可以看一下 g d k, 那么在这里呢,就会看到我们熟知的 j d k 的动态代理的一个创建,对不对?所以说呢, 它第一个地方就是在病的生命周期初始化之后,通过病的后置处理器的这个 post off 的 indishalization 方法创建 aop 的动态代理,好吧, 当然你要回到这个这个命题,你肯定要有一个前置的知识,你肯定要知道 i o c 当中的这个定的生命周期,对不对? 所以说我还是那句话,这些技术呢,都是连贯性的,并且 aop 呢,他也是依赖 ioc 的,所以说呢,你必须提前知道 ioc 相关的一些底层原理,如果你不知道的话,肯定也不知道我在这里说什么,对不对? 然后呢,还有一种特殊的情况,也就是在病的属性注入也是生命周期啊,病的生命周期属性注入这一步刚刚呢是在初始化,这一步不管是初始化还是属性注入都是属于生 命猪器当中的。那么还有一还有种情况呢,就是在属性猪入时呢,存在循环依赖的一个情况下,也会为循环依赖的病呢,通过病的后置处理器的另外一个实现,创建我们的 aop 的动态带领。 那么如果你不知道什么是循环依赖的话,去看一下徐树老师之前讲的这个循环依赖的面试题,好吧,那么循环依赖我们可以结合这个图看一下,在属性注入这个时候呢,他会去调用 属性注入,我看一下啊,他会在这里啊,他会在实力化之后,他会在实力化之后给他呢存到这个三期缓存当中,知道吧?但是他在这里不会立即调用啊,因为三期缓存他存的是一个函数接口,存的是函数的指针,他不会立马去调用这个方。 那么是在哪里调用的呢?是在属性注入发生了循环依赖这个过程当中去调用的,所以说他虽然是在这里去 去呈现的这个代码好吧,但是他并不会在这里调用,真正的调用呢,是在属性诸如属性副值出现了循环依赖才会进行调用。 ok, 好的,我们可以看一下, 我们呢,依然是依然看一下刚刚所说的 刚刚所说的这个动态代理的这个并的后置处理器按键动态代理的这个实现,它里面呢,同样的就也实现了这个 get alibing reference, 我们可以看一下这个方法, 这里面呢,我们可以看一下他是不是又 调用了这个 wop 衣服 necessary 啊,对不对?那么这里是不是又跟我们刚刚看的代码一样的,首先呢会匹配切点,然后呢匹配上了创建中的代理, 是一个方法呀,好吧,刚刚我们看的是哪个?是这个对不对?所以说呢,他会在这里先判断一下,你是不是在循环依赖的过程当中呢?是不是已经创建好了动物代理,如果在循环依赖当中创建了,那么我就不在这个初始化这里去创建了。 ok, 所以说呢,他这里已经做了判断,不需要担心两个地方都会创建好吧,所以说呢, 使命的 aop 呢,他会在两个地方进行创建,当然他不会同时创建啊,而是二选一,怎么呢?又是正常的病,好吧,正常的病会在病的生命中进了初始化之后去创建,然后呢 还有一种特殊情况就是循环依赖的病会在会在属性注入的时候呢进行创建, ok, nice。