00:00
动态代理,前面呢,我们讲了静态代理,我们再来学习一下动态代理,首先我们看动态代理的基本介绍三点。第一点呢,在动态代理这种模式下面呢,我们的代理对象就不需要再去实现接口了。大家还知道我们在进来代理的时候,是不是有一个接口,这边有个代理对象proy是要去实现这个接口的,现在不需要了,但是目标对象仍然需要实现接口,否则就不能用动态代理。第一点,第二点代理对象的生成呢,它实际上是利用JDK的API,这里面会用到JDK的反射机制。那他动态的会在内存中干什么呀?构建代理对象,注意它会在内存里,在这个内存里面动态的生成一个代理对象,不是目标对象。那么你返回一个代理对象过后,再通过代理对象去调用我们被代理对象的方法。OK,所以说动态代理呢,他有另外两个名称,一个叫JDK代理,一个叫接口代理都可以。
01:01
那么说到这里,我们要解释一下,他怎么在动态的在内存里面构建一个代理对象呢?主要是靠在这个Java no.reflect这个反射包里面呢,它有一个核心的方法叫new pro instance,这个方法会接受三个参数。Interface,还有一个invocation handler。那至于这三个参数到底是干什么的,我们待会再写应用案例的时候再详细给大家讲好的。这个是JDK里面用的一个核心方法,听这个名字大家大致能猜出来是干什么?六就是新创建一个什么呀,Proxy就是代理的一个实力。所以说通过这个方法呢,我们可以动态的返回一个代理对象,然后通过这个代理对象去调用我们目标对象的方法,它是这么一个机制,那现在呢,用这个语言描述太抽象了,所以说我们仍然用一个案例来描述动态代理是怎么使用的。
02:04
那待会儿呢,我们用静态代码,呃,用把前面的静态代理。把前面的静态代理改进成动态代理及JDK代理,我们还是老规矩,首先呢,画出一个类图,对,然后根据这个类类图,我们把这个代码怎么样给大家实现一把就可以了,来吧,现在呢,打开这里我们来新建。我们的这一个动态代理的案例,我们先建一个包包。Dynamic。OK dynamic,那现在呢,我们新建这个包的时候,我们我们先把这个类图画出来,各位同学这个类图呢,能够让我们很清晰的知道它是一个怎样的关系,来捋一捋。好,这些不要的,先把它关掉啊,先把这个关掉,这个咱们也啊留着吧,好,我们现在开始画,首先接口还是要要的,就是同学们前面念的I teacher。
03:02
Teacher DAO这个接口里面呢,哦,各位同学仍然是有这个方法的,哪个方法呀,Teacher。没问题。Teach,那我们现在有一个目标对象,目标对象对应的这个类我们就叫teacher d,显然他要去实现这个接口,既然实现了这个接口,显然这里面也应该有一个方法,哪个方法呢?就是它这个接口里面的方法,Teacher。没问题吧,同学们,好的,那现在呢,我们还需要刚才分析的这个代理工厂这里面这是跟静态代理不一样的,他会有一个pxy biy。这个是个代理工厂,那这个代理工厂里边呢,有两个最为核心的方法,我说一下第一个方法就是它的什么呀,就是它的构造器,这个构造器我们写到parkxy是吧,Biy OK。
04:00
好的,那这个这个构造器有了过后,它还有个什么呢?各位同学,它还有一个重要的方法叫get。Proxy,注意写啊,叫get proxy proxy代理的什么呀,实例,那么返回的这个类型,各位同学,它是以object类型返回的。OK,那大家看这个东西到底他用什么,用来干什么事呢?我先给大家做点注释。让大家清楚的知道他是干啥的,首先我们知道这个方法,就是同学们看道get p instance这个方法它是干什么呢?第一个他根据根据传入的这个对象,传入的对象哪个对象呢?到时候你会传这么一个对象啊,Teacher dl,这个显然是我们的目标对象。这大家能看懂啊,就是目标对象,他通过这个目标对象干什么呢?各位同学利用利用我们的反射机制。
05:04
利用我们的反射机制,OK。返回一个,返回一个代理对象。OK,代理对象,然后我们再通过这个代理对象去调用我们这个目标对象的方法,对,然后通过代理代理对象调用什么呀,目标对象方法。他这么一个逻辑。所以说呢,这个跟我们前面这个思路呢,是有一点区别的,好的,我先把这个他们之间关系勾起来,没问题吧,但是同学们可以看到I teacher do和factor已然没有关系,就从这地方呢,他们之间没有说,哎,我要去实现你这样一个关系了。好的,那现在我们还差一个什么client,那么这个client怎么用呢?各位同学,这个client呢,肯定会去依赖我们这个per factory,因为他要通过这个per factory返回一个代理对象。
06:03
注意是返回的代理对象啊,提这个名字get per instance不是返回目标对象,是返回代理对象,当然我在返回的时候,我显然要给他传入一个teacher do,这样对象通过他就说我给他,我给我这个get instance factory传进,哦不,我在这个构造器的时候,同学们我在做这个构造器的时候呢,会把这个teacher do传进去,然后他再根据我们传进去的teacher返回teacher do的一个代理对象,然后再调用他的方法是这么一个逻辑。这么一个逻辑,好听起来是有点绕了,听起来是有点绕,但是呢,咱们写代码一会呢,大家就能就能看到它是怎么用的,思路就这样子,那同学们我们走一下代码。那既然要走代码,我们就跟原先的这个思路呢一样,按照这个顺序来写就可以了,不着急,首先我们先写出这个接口,IDAOOK。
07:04
那这里面呢,刚才我们分析到它是一个接口,同时它有个方法是吧,这是一个接口方法,我们写一把叫做VO什么呀,Teach。没问题吧,那这里面呢,我们有个叫做授课的方法,写完。那么我们在写他的带,呃,他的目就是就说目标对象对应的这个类,目标对象对应类呢,我们前面想到teacher DAO是吧,显然他要去实现我们这个接口,这个没毛病,跟我们前面说implement。I teacher you,现在这个方法呢,我们跟前面类似,哦哦,写错了,不好意思。点错了啊,那就是实现,那这段我们仍然写一句话,就老师正在授课中。老师。正在授课,授课中。
08:01
喜欢。好,现在这个整完了以后呢,我们还差一个什么,同学们是不是我们还差一个part factory,这个最为核心。也就是说我们通过这个per factory呢,返回一个代理对象,然后通过代理对象去调用我们被代理对象的方法,好,那我们来看关键的地方了,我们写上part factory来走一个。Pro bikey OK啊OK,那根据我们前面的分析,他首先呢,他首先呢,他要去维护维护。他要维维护一个目标对象,这个时候呢,我们直接以object的形式来维护就可以了。好,我写上。OK,那同学们可以看到这个对象怎么传进来呢?好,我们通过构造器给它初始化。对的,这个super不要了,也就是说我们构建在构建构造器,构造器时干什么?对,我对这个target就是目标对象。
09:12
Target进行什么呀,初始化。OK,那现在我们最核心的方法来了,大家还有没有发现我们在前面分析了还有一个么?Get park instance这个方法最为重要,我们前面讲过,他返回这个被代理对象,11呢,它是通过反射机制的,所以说我们这边用到了一个方法叫做new。Instance,我们把这个方法写一遍,来走一个写个方法叫做给目标对象干什么,生成一个代理对象?好,我们来写一把public。Get什么呢?Proxy instance?好,其实这地方我们是可以将来proxy,我们就想想proxy get proxy in是是。
10:04
好的。好,同学们,那你怎么样返回呢?是不是刚才我讲过一个方法,现在要用了,就是这个方法。New proxy instance,那怎么去返回这样一个东西呢?同学们,我们讲到在这个类中,Proxy这个类里面它就有这个方法,那么我们来用一下啊,我就直接写了同学们,Return。Return什么呀,Pro点六意思看到没有,好同学们可以看到在这个地方。New里面呢,我们直接给他。对他的方法进行一个重写就可以了,好,我们不要不要乱写啊,在这跟着我的思路。好,那现在呢,我们对这几个方法,对对这几个参数做几个说明,认真听第一个参数,同学们可以看到这有一个no。
11:01
这有一个loader好,这个loader的话呢,我们这样子,我们把这个方法的原型拿过来给他看一下,其实它。看到没有,是抛这个类里面的一个静态方法。静态方法,那这个静态方法呢,我们要做一点点说明。我把这个写到这儿啊。呃,怎么写呢,这样写。对这个方法做几点说明,我们整理一下这个思路。第一个。同学们看到的第一个参数就是class loader。这个参数它是干什么的呢?它是指定注意听不着急指定当前目标对象,当前目标对象使用的类类加载器,诶这是什么呢?加载器。加载器。加载器OK,那么获取注意题,获取这个加载器的方法咱们是固定的,就是加载器的方法固定。
12:06
好,第二个参数我们来看。同学们看到第二个参数就是。这个interface这个是用来干什么的呢?郭同学,他是目标对象。目标对象就是我们将来要这个要要被代理的对象,他实现的接口类型。接口类型使用泛型方式,OK,使用泛型的方式确认类型。确认类型。好的,确认。确认好,把它改一下叫确认。确认类型,好,第三一个我们来看一下,第三一个呢,就是这个H了,这个H同学们看是invocation,然后handle这个是干什么的呢?我们写一下,这个是事件处理。
13:01
它是一个事件处理。事件处理执行注意听执行目标对象的什么呀,方法十。所以目标对象方法是他干一件什么事情呢?他会会去触发触发事件处理器的方法。都有点抽象对不对,呃,说的再直接一点,就是干什么呢,会把,所以小小啊,他会把什么呢?他会把当前执行的。这个目标对象,目标对象方法作为做什么,我们来看一下。它会作为一个参数。参数传入。也就是说,也就是说到时间我们这个这个H,我们这地方会接收到一个什么东西呢?在这个地方我们就会接收到这一个所谓的这个目标对象。
14:03
OK,那现在呢,我们来把这个方法要重新写一遍了,那这里面第一个参数来class,我们刚才讲的是目标对象使用的一家事情,目标对象是啥呀,是不是他呀,于是我们这大胆的进行一个改进,变成了它点什么呀。Get class是不是地方应该写一个,看看应该写什么啊,应该是target get get class点。点什么呢?Class loader,好,第一个参数咱们就写完了,第二个参数我们讲了是目标对象实现的接口,OK,那你目标对象target。对,使用反射机制get什么呀?class.get什么?Get它所有的接口,Get interface,好,H我们来看看,刚才讲过H呢,实际上就是我们要执行目标对象,那这个时候我们怎么去给他来一个呢?好,同学们,我们要这样写啊,这地方大家可能有些同学能够接受,有些同学可能一半会听不懂,看一下我就直接溜一个invocation。
15:15
OK invocation handler。好的,在这里边看,我在这个内部在传这个参数的时候,我以一个匿名对象的方式传进去,因为在这里面呢,他要去指定什么呀,指定当前目标,就是指定怎么去调用我们这一个目标对象的方法。大家可以看到invoke这个就是方法,那这里面怎么去调呢?怎么去调呢?怎么又返回一个值呢?好,同学们看,首先我们第一步要假如我在这写一句自己的话,好吧,我写一个叫做JDK代理开始。没问题吧?好,那这个时候我们要调用什么呢?调用这样可以这样写,通过反射机制。
16:06
调用什么?调用目标对象的方法?那问题来了,你目标对象是谁呀?目标对象同学们刚才已经看到是target。这个是我们的目标对象,Target。那你方法是什么呢?是VO啊,是这个method,也就是这个地方呢,它会自动根据你这个机制把你这个method给填进去,好了,那现在相信同学们大致明白是怎么来走的,那也就是说用method。点它这边有个方法叫VO。好,这里面第一个这个object填的就是我们。要被执行到就是目标对象参数就这传进来的,有就有,没有就没有,那么这样它会返回什么东西呢?OK,返回的就是我们这个执行的一个结果。执行的一个结果,那这个结果呢,我们就直接写成样子啊,叫比如说我们叫做的一个值,至于这个值是什么,是什么就是什么,因为你执行这个方法,有可能有返回值,有可能没有返回值,对吧,那没有返回值就空嘛,有有就有,那么就把它返回。
17:16
好。这就是我们这个方法好,这方是不是。哪个地方有有问题啊好,我们再来看看哪个地方是不是一个参数。多了呀。好,这个就没有问题了,好我们看一下这个方法,现在呢。在这里填进去了一个参数,两个参数好,这是第三个参数好的,呃,那现在最后这个地方我们应该有一个分号,这里有个分号就可以了,保存一下。好,还有一点小问题,我们把它。调一调,把它调一调。
18:00
我们调一调这个哈,呃,大家看这边呢,是有一个小括号对应的,呃,这边是六了一个这个这个分号不应该填到这。下面这两个呢,应该也不需要了,是不是也不需要了,所以说这个地方呢,应该这样子写,把它弄到上面去,这边打一个。分号啊就可以了,也就也就是说在这一个盖的。这个proxy instance里面呢,我们使用了proxy这个类里面的一个静态方法叫new proxy instance,然后呢,这边就返回了一个返回,就是返回了一个什么呢?返回了一个这个。就是我们代理对象,然后再用代理对象去调这个方法就行了,这个方法是我已经重写的了。就重写了invocation handler里面的这个方法,因此我们可以认为它是一个匿名子类。对不对,好的,那同学们,那现在这个写完了过后,我们是不是还差最后一步了,就是这个client,把这个client拿来用一下,大家就明白了,然后我再追一下源码,再追下源码,大家就一目了然好吗?Client把主方法勾上。
19:10
好,跟上我的思路,朋友们,那现在呢,我们来使用一下,看看怎么做。首先第一步我们先创建一个目标对象,目标目标对象,目标对象很简单,我们就六一个target。这是我们要去执行的,那既然你是目标对象,我用接口来接收,这也是可以的,所以说我把这个名字直接改成他给。目标对象也是我们被代理对象,然后下一步呢,干什么给我们下一步就这样做了,给目标对象。给目标对象创建什么呀,创建代理对象。代理对象,那是不是就用我们那个工厂类了,那怎么写呢,就用我们这一个。
20:00
我们我们这个地方不是有一个这个吗?是不是我们六一个这样的实例。又一个这个工厂类,然后通过他把这个target传进去。这个是我被代理的,然后大家还记不记得这面,就这这个方法我们就可以用了,Get。欧了。返回的来,同学们,我写到这来这个返回的呀,这个返回的类型就是我们代理对象,你可以认为是part instance,当然这个类型呢,我们就不能用object来接受了,因为大家知道我们刚才讲过,他返回的这一个代理对象的类型可以强转为,可以转成什么呢?转成这个I teacher。为什么?为什么?因为你传递这个target。这个对象。这个对象它是实现了I teacher deal这个接口的,因此呢,我们这方需要把它强制转成这个I teacher。
21:04
否则你没办法调查方法,因此在前面呢,我们要加一个强转符号。大家看清楚了,不着急啊,现在现在我们就拿到一个代理对象了,我们来输出一下这个代理对象的类型是什么,我们来看看part instance是什么来输出,同学们看一下,好,我们执行一把,当我们执行过后,你会发现呢,它输出的是这个类型。大家有没有发现OK啊,你看这句话已经执行了,大家看返回的是这个。诶有点意思,对不对,它返回的是这个东西。看dynamic teacher DAO一个这样的,所以说这个地方呢,是这个,但如果我们去拿到它的类型,各位同学看get他的class。Get它类,你会发现它类型呢,是一个这样的符号,看到没有,也就是说他这个实例的类型,其实就是我们。com上P里面的这个类型,只要你看到返回一个Dollar,说明他是个代理对象,明白际上他是个代理对象,所以说我们从这可以看出来是干什么呢?从这个地方我们可以看出。
22:13
看出啥玩意儿呢?就是内存中生成的对象实例。内存中。内存中动态动动态。太生成了,生成了什么呀,生成了代理对象。诶,代理对象有点绕啊,那现在呢,我们就可以用代理对象来调我们的方法,然后再干什么,通过代理对象调用是没有调用我们目标对象的方法明白,他说老师你怎么调啊,没问题,来看pro instance,我调他的这个teach方法吊起来了,来运行一把,我们可以看到此时此刻你看代理开始授课中,那现在呢,如果我在这再加一句话,大家就看的更加明显了,在哪里呢?在我们的part这个代理工厂里面,我们是是不是这写完了过后还应该再加一句话就更明确了,就是这吗?在这再加一句话好吧,加一句话说JDKJ,因为往往我们在。
23:17
调调这个核心方法的,这里面这个方法会找到哪去呢?会找到你这个。被代理这个对象的那个方法去,那你他通过什么来区分呢?通过你的参数啊,不是通过参数啊,是通过你这个这个地方调的这个地方来来看的,待会我再追一下,大不着急就说你这掉了teach,他就知道掉的是这个提取方法。啊,待会我再给你们追一下就可以了,那现在我再写一句话叫JDKJDK代理。代理提交。好,我们再来执行一下,你们可以看到这句话也会被执行来朋友诶,呃,保存一下这个问是不是有问题,没问题啊,我现在运行值,那运行过后我们可以看到,诶的确这样子的,那到底它是怎么生成的呢?来各位朋友我们追一把,那现在追我们关键是要往这个T方法内部追,是不是我运行一下,来朋友们,我们第8UG。
24:12
我们debug OK啊,来,Yes,我们往里面跑一跑,看看它到底是怎么执行的,来,走,注意看啊,我追进去。进去了大家可以看到,我们再跳出来一下。好,他这个这个打印,我我们我们是不是定错位了,看一下这个定错位了,是不是来重新来。他怎么跑这去了呢?是不是我原先下的有其他的断点?好,先把其他断点删一下。三峡。好,我再我再重新来一下啊,在这下个断点。在这下个端点就可以了,其他地方我们不要再去追了,来再来走。B。好的。好,现在已经走到这来了。
25:02
他现在走到这个T过后呢,显然我们现在追到这个teach方法里面去追这个。好,同学们看到这来了,诶你们有没有发现,其实他就找到了我们这个返回到,就是我们返回这个代理对象的这个方法,Invoke里面的这句话。是不是这句话,也就是说这句话。那么现在我们来看一看同学们,你们注意看method是谁,这个method其实就是我们的teacher方法,是I,大家看是我们I teacher道里面的teacher方法,看到没有,他怎么知道是这个方法呢?因为你在用代理对象。动态生成的代理对应调的时候,你写的是提取,那我们再来看这个参数有没有参数,现在是空,因为你没有,你你这个提取方法是没有参数的,说是空,如果你调的这个方法有参数,那么参数就会放在这个argue这个对象里面啊,这个数组里面去。
26:00
好,我们往下执行。好诶,看到这里这句话,同学们,这句话会直接导致我们的哪个呢?被代理对象的,也是目标对象的那个提取方法被调用,注意看往下走一步。我们可以看到老师授课中被调用起来。好,接着再往下走。代理对象提交把计划值,然后返回这个值,如果有值就有,没有就算了。如果有值就就返回,没有值就算了,明白吧,因为你在代理这个。你在代理这个方法,这个这个方法有可能有值,那我给他再加一点东西,你们就可以看的很清楚了,来我们在这面再稍微的呃,改进一点点,比如说我现在除了有一个贸易的方法过后呢,我还有一个,我还有一个这样的方法来看。Voy say hello。Say hello,来,同学们看,比如说我在这里面接收一个名字。接收一个名字,这两个显然不一样了,那这一保存呢,同学们可以看到此时此刻,诶先把它停下,此时此刻teacher DA里面也要去默认实现这个方法啊,要实现这个方法对不对,加一个,那这边我们就打这样一句话,输出叫什么呢?当然我也可以return哈,我就没有输出了,就说hello。
27:20
把他的名字输出来。是不是,同学们看到没有?好,那现在如果我在client里面调的时候,我是这样调的,同学们看instance点什么呢?Say hello,同学们看,我写一句话叫汤姆。好,我先把这个注销,那注销过呢,我们再来注意一下这个源码,你们就知道,诶那个参数是怎么加进去的,来走一个,来同学们DEBUG1把。第八个亿吧,OK yes,现在呢,我们现在把代码进进到这个c hello了,我们仍然追进去,注意听,我们仍然注意,诶追到这了,接的一个代理开始往下走,大家看到这个method,因为你在用。
28:01
这个代理对象调的时候呢,你调的是C号,所以说这边返回这个方法呢,因为方法他也看成是一个对象了,在这个代动态代理里面,他把方法也看成一个对象。Method是个对象,那就是什么呀?C hello,同时同学们注意观察这个argue,就里面有个汤姆了,看到没有,诶,就这样传进来的,那你往下一执行,肯定它会输出hello,汤姆。往下走是不是hello time出来了,好,然后再往下面一直行。代理提交完事。同学们,通过这个地方,大家有有发现它的特点哈。我我我把这个都都不要了,注销了,你们你们要注意他的特点,它的特点就是什么呢?在我们这个动态代理过程中,它是没,它是动态给我们产生一个代理对象的,我们以前是溜出来的,那你要多少个,你直接从这用他这个part factory去。取就行了,去取就行了,好,这就是我们动态代理,动态代理的一个小案例,同时呢,我们也把他的这个类类图也画出来了。
29:09
好呃,大家再体会一下,最后呃,动态代理呢,我们就给大家聊到这里。大家好好去体会一把。
我来说两句