00:01
设计力代理,前面我们讲到静态代理,讲到动态代理,我们再看。CG代理,那我们还是老规矩,按照。他的一个基本内容来做一个介绍,那首先我关于他的基本介绍呢,我整理了有五点,大家听一下哈,就静态代理呢,静态代理和这个JDK代理呢,他都要求我们目标对象去实现一个接口,还记得吧。不管是静态还是动态,动态代理还是这个JDK啊叫JDK代理,他都需需是需要实现一个接口的,但是有些时候呢,我们喜欢,我们希望这样实现,比如说我有一个类A类。OK啊,那这个A类里面呢,我们我们这个A类呢,并没有去实现任何的接口,它没有实现接口。明白我的意思吧,他没有实现任何接口,那现在呢,我也希望有一个代理类叫pro,比如说per factory。这个呢也能够实现,对这个A类,也就是我们这个。
01:05
目标,目标这个类对应的它的一个一个对象的代理。也就是说我们被代理对象呢?他没有去实现接口,我们也希望能够代理他。明白,也就是说这个时候呢,它是个单独的对象,并没有实现任何接口,这时如果要按照这种方式来实现的话呢,我们需要用的是CG代理。OK,那么C级代内部代理呢,他还有另外一个名字叫做子类代理。他在内存中构建的一个子类对象,从而实现对目标对象功能的一个扩展,有些书上呢,直接把这个CGD代理归属到动态代理。因为它也是动态的一种形式,就是在内存里面来实现这个子类,从而实现代理的。那cg lib呢,它是一个强大的高性能的代码包,也就是说如果我们要用cg lib代理,我们需要引一个包,这里面这个包里面呢,有四个炸。
02:02
里面是需要我们需使用,使用到的这个类都在里边,那而且要给大家讲一下,就是这个CG力呢,被广泛的被许多a op的,像这a op的这种框架所使用,比如像spring op,它实现方法拦截,它就用到了这个C包。那么我这里再总结一下,什么时候选用JDK,什么时候选用CB呢?就看他的要求,如果说他们要求目标对象需要实现一个接口,我们就用前面讲的这个动态代理的JDK代理。如果这个目标对象呢,他要求不实现接口,直接就能代理,我们就用CD代理,OK,那最后说下CD代理的它的一个底层原理,它的底层呢,是通过自节码处理框架,一个叫什么框架呢?Asm来转换自己并生成性的类,这是它的基本介绍。
03:00
关于这个基本介绍,可能有些同学听起来也比较的抽象,总而总而言之,大家记住一个核心点,就是CG内代理呢,他在代理一个对象的时候,这个对象他可以不实现任何的接口,再说一遍,也就是说CG代理呢,他可以代理的这个对象,他不需要实现任何接口。我们也能够动态的代理这种。对象就这意思。好的,那明白这个道理过后呢,我们还是老规矩,呃,我们就来把cg lib的一个实现步骤给他聊一遍,首先我们要用cg cg lib代理呢,我们需要cg lib相关的这个炸包,这有三个炸,四个炸包,待会呢,我们已经给他准备好了,加进去必须有。第二点。在内存中构建这个子类,注意有一个细节,我们代理的类不能是B类,也就是说比如说我这有个A类,我需要被代理。我需要,我需要代理这个A类,那么在c Li里面要求这个A类不能是B类,如果是B类它直接报错,为什么呢?因为这个B类它不支持在我们的这一个C机里面动态的创建它的子类无法实现,所以说如果你这样写呢,它会报一个错误,叫做非法的argument exception,就非法的参数异常。
04:17
这点请大家注意一下,还有一点,我们最后代理的这个A类里面,肯定是准确的讲是代理他其中的方法,比如说A类里面有个M1方法,有个M2方法,那么有一点需要给他们说清楚,我们目标对象的方法,如果是final或者static,那么就不会被拦截。因为他在用cg Li代理的时候,他其实本质它是通过拦截器的机式来处理的,如果你这个方法是是final或者静态的,它不能够支持。不能支持啊,这里面涉及到一些。Java的底层的基础原理,这个呢我就不去多啰嗦了,我主要把CG代理的一个流程给大家讲清楚。好,同学们,那现在呢,我们老规矩就用c lib把前面的这一个案例重新改写一遍,还是老规矩,首先画出我们的内图来,同学们,打开我们eclipse,我新建一个包包。
05:14
新建一个包,这个包呢,我们取个名字。叫cg lib。She Li。好,同学们,那跟上我的思路,我跟上我的思路,我们来看一下怎么去实现我们这个cg lib的一个代理,把这个图片给大家看一看,大家就一目而了然了。好,我们来看一下。新建一个。累。没问题吧,好,新建一个内部。好的。好,那这个做出来过后呢,我们接着再往下面看,接着再往下面看,我们来把它的对应的这个类图给大家简单的画一下,一目而了然,首先我们先画出什么呀,先画出这个被代理的对象所对应的类,比如说teacher DAO各位。
06:08
这直接就是我们被理的这个对象了啊,当然是这画的肯定是类啊,因为有时候说的时候呢,说代理类好像有点不合理,就说直接说被代理的这个对象对应的类也很绕口,直接直接就说被代理的对象大家应该能听懂。好,这里面呢有方法。OK,这里面有方法,我把它写这里面,这个方法呢,就是前面我们写过的很多遍的teach。OK,写完写完过后呢,同学们可以看到我们还要写一个类,这个类就是我们的proxy factory这个类。OK,那这个类呢,我们讲过cg lib,它是基于拦截器的这种机制,所以说它需要去实现另外一个接口,我们看这有个接口叫什么呢?同学们叫Meta。方法,Intercept。
07:03
Inter intercept OK,这是一个方法,拦截器需要干什么呢?被实现。啊,待会同学们可以看到,那在这个part factor里面呢,我们需要写几个比较重要的属性和方法来看一下。首先有一个属性,大家必须知道,哪个属性呢?就是我们被代理的这个对象。OK,是个object。他仍然会被聚合到我们这个part factory。因为我要代理时候,我连你的类都不知道,对象都不知道,那我怎么代理呀,是不是第二个呢,里面有几个比较重要的方法,给他写一写第一个方法。还是我们的这一个构造器pro factory,通过这个构造器呢,我们可以把这一个teacher到的一个对象给他,怎么样聚合进去,那再来还有什么方法呢?同学们,还有一个方法就是我们讲的刚才讲的叫get proxy。In势。
08:01
Instance in。Instance,好的,那返回的这个对象是object,也就是说get instance就是返回一个代理的对象。明白带返回一个代理对象啊,不是返回这一个目标对象,再说一遍好了,我们还下一个就是这个方法在哪里去调用呢?返回这个代理对象怎么去调用呢?各位,我们需要在这里有一个方法intercept需要去重写intercept intercept intercept,这个方法要重写好,大致就这样一个逻辑,他们两者之间。从这里看出来好像是没有关系的,对不对,其实到时间还是要聚合进来,只是呢,呃,这个它是DATDAO,把它放到这个target target里面去。好,现在呢,我们还差最后一个就client。Client从直接来说,这两者之间没有,我再不去继承他也没有实现它啊,那client怎么用呢?会用到它,也会用到它就完事了。
09:05
所以你们有没有发现,通过这个图我们可以清晰的看到。在这个类图里面,我们不再有接口了。所以说我这里总结一下来,同学们。我在这里总结一下。好,我们来看看。嗯,针对这个part factory呢,我们总结几句话。来聊聊,诶,这个地方怎么没有哈,来我们聊聊这个诶。好,聊一下这句话,它是干什么呢?它是目标对象。给目一个就是给目标对象。给目标对象干什么呀,Target?他给。他。Get干什么呀?创建,创建一个什么呢?代理对象,也就是说同学们看到的这个get instance这个方法写到这get instance。
10:00
他是给我们的目标对象创建一个代理对象,这点大家要清晰,第二点呢,需要重写什么呀,Intercept intercept就比intercept别写错了。In。Intercept。哦,这个方法。这个方法,这个方法呢,要实现什么呀,实现对什么呀,代理对象。代理,也就是我们这个目标对象。代理就是对象,就是我们的目标对象,诶不对不对啊,说错了啊,这个实现对什么呀,对。应该是这样写的,就在这里面,Intercept里面呢,要实现被代理对象啊。实现对。对,这个被代理对象,也就是我们目标对象的什么呀,调用。是不是方法的调用。方法的调用。调用。明白。
11:00
也也就是说在这个intercept这个方法里面呢,我们会去实现什么呀,实现对这个target,也就是我们这个被代理的对象,也是我们目标对象的一个调用,待会呢,大家通过这个代码就能一目而了然的看出来。好的同学们,那关于他的类图我们就说到这儿,下面呢,我们给各位同学具体的走一下它的代码。走向代码功能,大家就非常的清晰,它的流程是什么样子的。那现在呢,我们来开始写这个代码,我们先写哪一个呢?我们还是老规矩,先写这个teacher道好不好,很简单的写一个。来,走一个,这就是一个实实在在的内容,不是借口,Teacher。OK。那同学们看一下这个teacher到呢,在这里面我们应该按照原先这个思路直接写方法就可以了,因为它不实现接口,直接写了void什么呀,Teach。提取好的,那这里面我们就输出一句话就OK了,输出哪句话呢?写一个我们这面写一句话叫做老师授课中。
12:09
老师授课中。没问题吧,那这地方我写提示一下啊,我是。我是cg lib。啊,代理不需要。代理我不需要什么,不需要实现接口。以前是不是我们这个目标对象都要实现接口,现在不需要了。第一个咱们就写完,紧接着我们来写他最核心的这个part factory,这个呢,稍微长一点,呃,这个内容稍微多一点,大家认真听。好,写一个叫proxy。VI。没问题吧?根据刚才我们聊的这个话题,根据刚才我们聊的这个话题,我们在这里呢,需要去实现一个接口,哪个接口刚才是不是已经说过了,就是我们的method。
13:02
Method。A said。诶,这个内容怎么没出来呢。就是OD。OD,然后呢什么。In。什么呀,Intercept。Sector。好,那大家可以看到,呃,Method inter intercept这个地方我们没这方,为什么没有看到东西呢?我们来先看一下来。看到这样,他不让你引入,因为这个me instruct呢,它其实是在我们这个cg lib这个框架里面的四个包里面,所以说我现在需要引包了,来同学们打开它,我现在呢。这里面有四个炸包,我要把它引一下,同学们好,我把这十个包引到我们项目里面去。好,我先粘一下。粘一下功能,我把剪切到郭同学剪切到我们这个CG项目里面去,没问题吧,好同学们,我把这个呢加入到我们代码中去。
14:03
加入到我们这一个。路径。OK啊好,这时呢,我们再来玩一把,再来一下,来走一个。好,我们引一下这个包。好看一下method intercept。好,可以看到引进去了,对吧,引进这个包了,看c Li它在这里面好引进到这里面呢,大家知道这个接口里面呢,有些方法需要我们重学,其中有一个最重要的方法,我们看一下哪一个方法就是一个in inside,刚才我们已经讲过吗?在刚才这一个类图里面,我我说过这个事了,已经。是不在我说过这事,他要去重写intercept intercept这个方法,这个方法里面呢,将会实现对我们这一个什么呀,对我们这个被代理的,也就是我们目标方法的一个调用,目标对象的方法的调用,来写一下源码。
15:02
首先第一项,它这里面呢,也要聚合一个或者维护一个都可以啊维护。一个目标对象。目标对象没没问题,那我开始写了private什么呢?仍然是object这个类型。因为object所有对象的,呃,所有类的类target放进去,紧接着呢,我们需要做一个什么呀,构造器。走,走一个构造器,CTRLS,诶,好O。把这个target给他放进去。各位。这是我们的构造器。这个构造器的作用就是传入。OK,他要传入一个什么呢?诶,他要给传入一个被被代理的对象是什么就是什么,是什么就什么,那最后呢,我们还有一个特别重要的方法,就是在我刚才分析的时候,里面还有一个方法叫get pro proxy instance,是不是这个方法要写一遍啊,来走一个public什么呢?Object。
16:05
Get proxy in。好,我对这个方法呢,做一点点小小的注释,我说一下这个方法干什么,是返回。啊,返回一个代理对象。代理对象,但是这个代理对象是谁的呢?是这个。Object的专利对象。是我们这个当前这个目标对象的代理对象,不是别的啊,所以说他跟这个是有关系的,是什么呢?是。是这一个target。这个。这个对象的代理对象。OK,不然的话,你你这个没没整对那就不对了啊,对象可以了。OK。好,那盖在里面我们需要怎么写呢?来四部曲第一步,第一步我们需要创建一个工具类。
17:00
第二步工具类,第二步跟上我的思路,第二步要设置副类,它的副类是哪个?负类。第三一步,同学们,第三一步呢,就是设置回调函数。回调函回调函数第四一步各位同学,第四一步是创建这个子类。指类对象及及什么呢?代理对象。OK,好,四部曲我们一步一步完成。首先如何创建一个工具类呢?六。一个enhance。诶,这个地方怎么写错了,不着急啊,这边可能需要引包的an an好像是这样写的,Cer好像是。好,我们先引下包,是不是需要引包哈,这个有点忘了。加一个包,诶引进去了是哪里呢?也是我们CG里面的一函式,它是一个电源包,好分分配一个变量。搞定第二步,设置它的父类,那它的父类是谁呢?Enhancer。
18:04
点他的super OK。让我看看是不是site。呃,下的Su super应该是super class,设置它的父类,这个副类。的类型应该是target.class。OK,第三一步,设置回调函数,那设置回调函数已然是enhancerhancer。点什么呢?Set它的call back,那问题来了,这个回调函数应该是就是他自己。啊,回答就是到时要回去反过来吊水调查自己。调查自己。好。最后我们返回他的就。什么呀,Return,我们用in点。点这个enhance。点create create一个对象,这个就是我们的代理对象,当然这个地方大家可能看起来有点有有点不太明白啊,这里面呢,我说了这个跟我们的。
19:06
跟我们的Java的这个底层有缘有一些关系,但是因为呢,我们这讲的是代理模式,说这块呢,我就不去深讲了,如果讲这块那是属于对Java的一个底层原理的剖析,我这就不去说了,你们就明白一件事情,就是说通过cg lib提供的框架呢,我可以返回一个代理对象,谁的代理对象呢?就是我们这个目标对象的代理对象就可以了。好,现在最后一个我们要重写。干什么呀,我们来把这方重重写一下这个方法,重写这个intercept,这个拦截方法。这个方法里面呢,方法会调用,调用我们目标对象的相关方法。OK,有点类似于我们前面的那个evoke,有点类似,好,来玩一把。呃,那么首先我们来看一下这个地方怎么写哈,怎么写来一步步的走。
20:03
来一步的步骤,首先呢,我在这里先提示一句话,System。好,我写话叫做cg lib。代理模式有点绕,对不对,然后呢,这边比如说开始。开始了CD。代理模式开始,那大家想一想,我们讲过,因为你在这里底层使用的相关反射是不是这个方法,就是就是把你的这个方法就做成了一个对象啊,叫二一,好,既然是二一,那么我们这地方就可以通过这个来调用就可以了,那也就说我们这方用个二,那这个名字有点不好写写啊,我们就叫method这样。这样好好看一点,对不对,好看一点,Method用这个方法来调点什么呢?同学们点invoke,它也有invoke好传东西。这个。就是我们要传进去,那这个地方我们取个名字,呃,我看看哪一个是我们的目标啊,不,这个要去掉的是target的,所以说这方填的是target。
21:05
参数是哪传进来的呢?参数显然是从这个地方传进来的,所以说我们这个地方也把它改一下叫as,这样看起来比较清晰一点。传进去好,他调用过后呢,会返回一个结果,为什么?因为你你是反向代理调用这个target的一个方法,这个方法可能有返回值,也可能没返回值,但是不管怎么样,你要接受一下是不是,也就是这种是跟我们原先讲的动态这个JDK代理很像,也是有个返回值的,是这个返回值有可能是空,也有可能不是空,对不对,所以我写个return value。最后返回这个value即可。那这地方我提示最后一句话。这里我再加一个,因为要拦截嘛,相当于说你在执行这个方法的时候,Intercept就会被调用好,这里我写另外一句话叫C代理提交。OK,提交代码就写完了。
22:02
是不是有点绕啊,也就是说。他获取到一个代理对象,然后呢,你调你去调他某一个方法的时候,就会触发这个intercept这个方法,这个方法里面去会去调用我们这一个目标对象的方法完事。其实整体思路跟前面很像,只是呢,只是他不再去实现。一个接口了,就他不需要实现你指定接口,我,而我们这个被代理人,被代理的对象呢,也不需要去实现接口,仅此而已。那同学们,最后我们是不是有client来教育吧?那我们要写一个class,写上。OK啊。那根据刚才我们分析,我们在这门调的时候呢,仍然需要去有有一个practice factory,有一个teacher do。好,那现在呢,我们就来把它处理一下,根据前面思路,首先第一步我们先创建目标对象。
23:04
那目标对象非常简单了,那就teacher嘛。要问teacher到。TE。T。Teacher do。是这里面的吧。产生一个对象,这个是我们的目标对象,没问题吧,现在呢,我们来干什么,获取到获取到代理对象。并且注意听并且将这个目标对象。目标对象传递给。传递给我们这个代理对象。啊,传递给传递,传递给这个代理对象啊,代理对象。好,那这个就很简单了,咱们就直接用一个part。这个工厂,这个工厂里面呢,我们把这个target传进去,诶他这方应该写成什么呀。那这个叫target比较合理啊,因为这是我们代理嘛,这个名字我就不改了,然后点get。一个实例,好,这个时候呢,它会返回一个,哦不,这个显然这个地方我们知道他返回这个代理对象,我们要把它转成哪个teacher到,不然你调没法调啊好。
24:10
转一下就可以了,转完了过后,同学们,下面第三一步干什么呢?就是执行执行代理对象的一个方法。代理对象的方法,这时它会在它底层会去触发,它会去触发哪个呢?Intercept intercept inter intercept这个方法,从而。啊,从而实现。从而实现什么呢?从而实现这一个,呃,对对目标对象,目标对象的。对象的调用。完事了,那同学们,我们来玩一把proxy。我们代理的实力点。好,我们来看看是不是跟我们想象的一样。来,我们追一把把这。
25:02
追下。同学们预习一下第八个。那第八个都同学们待会会看到我们会追到那那个inter intercept那个方法去好的。好,同学们,我们追进源码。可以看到这,诶你看果然到了intercept这个方法,好,下面呢,我们往下走一步输出了,大家看这个地方,这个method,你们如果观察发现,诶就是提取。有没有发现?那么如果有参数,现在肯定参数没有啊,如果有参数有参数的,这因为现在我们没有参数,所以它是个空的数组。对不对,但是这样一执行,它会掉什么,掉这个target的。哪一个方法呢?Method方法。因为他是反向反向处理的,说用用这个target这个对象,这个target对象就是teacher teacher到调什么,调method谁method是什么,Method是teacher。那显然就会输出这句话了。往下走。是不是输出来了没问题吧,同学们再往下面执行说这句话,再往下面执行返回结果,因为这个地方没有结果,就那就没有返回了。
26:05
啊,如果你有返回的具体结果会被谁接收到呢?就会被这个client的这个地方接收到,你可以接收吗?所以其实这地方可以本身现在也可以接收一个值,只是个空的啊,你看这样可以接受到一个结果。对吧,诶我们看看是不是这样子的。哦,这个不行啊,这这个在这儿不能接,不能接受啊,因为你提取方法本身没有返回值,你怎么能接收呢,对不对,除非你确实提取有有返回值,那他可以接受了,我们可以试一下。比如说呃,我这稍微改进一下啊,比如说这个T。啊,比如说我们这个T做完了以后呢,我返回了一个结果。假如说啊瑞return了一个it,返回了一个什么呢?返回了一个。字符串法叫hello,没问题吧,同学们,假如它返回一个哈,显然你这有哈,是不是这地方也会?写成一个哈啊是不是这这其他地方不用改,诶这个地方我要终止一下,然后他在代理的时候,是不是他执行完了之后,这个奥的呃,Value也就会被返回,那么被返回到哪里去了呢?各位朋友好,他就返回到他了,因为你的提前有方法,我们可以接收一下。
27:14
那么这个时候它会进行一个转换,对不对,那现在我们看一下返回的值是什么。就就叫呃结果吧,Res,等于我们来看一下这个返回的结果是啥。好,我们现在还是往里面追一追来吧,同学们。我们还是根据前面这个思路来追一下。这个他说没有用啊,没有用的话。Res,等于我们先来看看这个结果跟我们想的是不一样,首先它返回的是什么呢?它返回的应该是个hello。这个是肯定的,那么我们往里面追一下源码,看看在他底层进行这一个拦截的时候,它是不是也是返回这个哈,应该是一样的,对不对,好,应该是一样的,来朋友们追一把,来,走到里边去。
28:03
往下走。好,注意看现在value没有东西是吧,往下走。哎,你看。看看是不是hello啊诶就是哈,明白了明白了,好的同学们,那关于嗯,那关于我们这一个。C的这个讲解呢,我们就到这个地方,大家应该还是理解了吧,我觉得也不是很难对吧,也不是很难,主主要是你要搞清楚它的区别,它的区别就是说我被代理的这个对象呢,无需再实现接口,我用c g lib。这一个这这个方式啊,生成了一个一个代理的子类,然后返回去调用相关方法。好,那关于实力的代理模式,我们就聊到这里。
我来说两句