00:01
各位同学大家好,下面呢,我们继续来看这个代理模式,刚才呢,我们说了一个静态代理,大家发现他的问题,第一个静态代理呢,他并没有把日工呢给它分离出来。并没有做到对于日志的统一管理,它还是写到了代码里边,这样的话并不具备任何的灵活性,所以咱就需要用到这个动态代理进行实现,那动态代理它是怎么一个过程呢?咱们把这张图先看一下,然后咱用代码具体把动态代理做个实现。那这个图给各位来解释一下。我在这位置待会大家看一下啊,那咱们动态代理怎么做的呢?大家看过程中就是首先我们肯定也是见个代理类,但是它跟静态代理的最大区别是什么呢?我们不需要每个部分或者说每个功能中都建个静态代理类,咱只需要动态创建一个,不管你是什么那个目标类或者目标对象都为他建这么一个代理类,然后在里边你看啊,咱们把日志做统一管理,在操作前,在操作后,而这个时候我们调方法的时候,不管你调什么方法,它都会在操作前、操作后进行日志输出,这就叫动态代理,实现了咱们达到的效果,把日志统一进行管理,不需要每个部分都建个代理类,然后他也做到了在方法前、方法后进行日志的输出,对于他,做到了真正的解偶过程。
01:36
那下面咱就用代码把这个动态代理做个实现,咱们看怎么来做,首先啊,咱们看一下JDK里边的API文档,我这个的是一个在线文档,就Java的,然后在里边呢,我们搜索这么一个对象或者一个类,这个类的名字叫。就这个类大家看啊,在这里Java包中的process,通过它来实现动态代理过程,那怎么做呢?我们看一下啊,在process里呢,这里有一例代码,其实就这么来做,它里边有个方法,通过它来建一个代理对象,就是动态代理,那我们找到这个方法,咱们往下来看啊,大家看这个方法,在这个位置new process instance,通过它创建代理对象。
02:31
然后在里边的三个参数,第一个叫。这是什么?是不是类加载器?第二个叫interface,就是你接口的这个类型,第三个叫e handle,就是咱说的处理器,就是咱最终个真正做日志的那个管理部分,就在这里边进行实现c handle,然后c handle里边大家看里边有一个方法叫e work,这方法中就写我们那个具体那个日志那部分,比如在之前之后输出,然后里边你看啊,有代理对象,有你的方法,有方法中的参数,咱们可以在方法前方法后进行日志的输出,这是咱们看到的这么一个类pro里边这个new pro能用动态代理创建对象。
03:22
这是咱们对于API文档的一个查看,那下面呢,我们用代码把这个具体做个实现,咱们看这该怎么去做,给各位来写一下啊。这么来做,里边我来个这个名字。这个factory啊,就是为了这个代理对象或者代理类。这个我们做创建,然后创建之后呢,在里边怎么做呢,给大家写一下啊,首先我们建一个方法,然后这个方法呢,就返回咱们那个代理的对象。
04:03
这里写下啊,就是创建一个方法返回代理对象,但这个对象是动态键的,这个动态代理这个对象,那咱写个方个咱是不是有我们的目标对象,比如现在我要让这里边的方法在之前之后有日输出,这就是咱的目标对象,就要把目标对象进行传递。写一下啊,目标对象传的方式跟刚才一样,咱们来一个private,这里边呢,就不要写这个计算器类型了,因为咱要通用的嘛,所以来一个object类型,我起个名字就叫target,就是目标。然后咱们用它的还是构造,把这给他直接进来。这是我们写到的啊,里边这么一个目标对象的传递方式,这是我们做到的,然后咱再重复一遍啊,我们的做法就是首先建个类,在类里边写个方法,让方法返回我们的代理对象,就是动态创建这个代理对象,然后咱把目标对象要进来,因为咱要写的通用,所以类型就写成object,通过有参构造把它传递。
05:26
最后咱们在这方法中来动态代理创建这个对象,那咱们看怎么来做啊,给大家写一下。我们的做法就是呢,按照我们刚才看到文档中说明,调用里边的这个方法叫new实现,那咱们来写一下啊,我小这位置。注意包别错啊,Java包中的里边有个方法叫new instance,然后最终它返回到就是我们的一个对象。
06:00
这个就是那个代理对象啊,咱们把它就先直接吞一下。直接加个旅。这个对象,然后在这个方法中呢,有三个参数,然后把三个参数呢,为了咱看着方便,我就写到上面了啊,咱们加上它的三个参数。我在这个位置呢,给大家做一个注释啊,咱们来写一下,因为刚才咱们文档都看到了啊,里边的new instance方法,这里边的有三个参数。瞧这位置啊,有三个参数。然后三个参数分别是什么呢?看一下啊,首先第一个参数我们看这个文档里边咱们找到啊,回到这里,呃,看到这个方法,在下这里第一个参数就咱说的类加载器,我把这个给大家直接复制过来啊,咱们给它描一下,然后写代码。
07:01
第一个参数就是咱说的类加载器,也就是说加载动态生成代理类的那个类加载器。啊,加载动态生成这个代理类的这个类加载器。这就是第一个参数,然后咱们继续来看啊,下面再看它的第二个参数。我瞧这位置啊,第二个参数,第二个参数是什么呢?我们看文档中写到它叫interface,注意它是一个class类型,那这个什么意思,给大家写这位置啊,这里我来写一下啊。它的含义是什么呢?就是我们目标对象实现的接口类型的class啊,这个我们写到这里,当然一个,它就是一个类,可能实验很多接口,所以它表示你所有实验接口的class,这个数组结构,大家看这个文档中写到是不是一个class的数组啊,它是这么一种形式。
08:07
我把这个啊给大家复制到更完整点。有这么一个结构。那我写一下啊,它指的就是。我们里边这个叫目标对象实现的所有的接口,因为它可能实现了多个接口,咱目前就是一个实际中可能有更多实现的所有接口的这个class类型的一个数组,啊,这就是第二个参数,然后咱再来看里边还有第三个参数,第三个参数是什么呢?看文档中写到它叫做invocation handle。这个咱们拿过来啊,Invoc handle,这是什么意思呢?你可以认为就设置代理对象,实现目标对象方法的过程,就是比如说我们现在在我们调加减乘除之前之后做输出,那这个过程就写到evoc里边。
09:06
我写一下啊,就是我们。这么写,设置代理对象。它实现目标对象方法的这么一个过程,比如在之前之后输出那都是写到evoc汉字里边,这是咱们对于它参数的说明,这位给先知道啊,然后下面我们来写一下啊,我把参数呢就分写到上面,然后咱给它传过来可以了,首先第一个先得到它这个类加载器。我这里写一下啊,就是第一个参数,咱先把这个得到。类加载器,那我写一下啊,加上一个class。咱们叫car。等啊,我就把当前这个就是目标对象这个直接就可以了,咱们加这个target,点上class.get load,这个得到就是类加载器,是咱说的第一个参数。
10:11
然后下面我再写第二个参数。把这个拿回来啊。第二参数是什么呢?目标对象所有实现接口的数组形式,那我们加上这个target,点上get class,在点上叫get interface,这咱们之前提到过啊,得到它里边所有实验的接口,因为它有很多实验的接口,也可能是一个,最终得到是一个数组形式,叫interface。这是我们的第二个参数,然后之后下面再写第三个参数handle,就是我们实现那个具体那个。方法前方法后输出这个过程大咱们写部分,然后这个怎么做,看文档里啊,我把这个点大家看一下。
11:06
是不是一个接口啊,所以咱们接口里边它有一个方法叫咱就可以实现它这个方法最终就做到这过程多种写法,你可以写个类,然后实验接口,或者说用那个匿名内部类都可以做到啊,那咱就快速写个匿名内部类,然后实现已work方法,在已work里边使用我们那个之前之后输出过程。那咱们最后写一下啊。上一个叫invocation handle给下,然后的过程中啊,在里边我们实现它里面那个具体那个方法。这个方法咱可以给他。找一下啊,这个方法,它的方法就叫EVOC啊,这种作用实现,然后咱给他先起个名字就是invocation handle。
12:01
起个名字啊,就叫看到了,这是我们写的一个结构,然后最后那就是在这个方法中写咱们最终这个过程啊,那我们来写一下啊。大家看这方法中啊,有三个参数,咱们说一下什么意思。这位置啊,第一个参数指的是什么?很好理解,就是咱们这个代理对象啊,这是第一个参数,然后再看第二个参数。大家看是什么,是不是叫method掉,这是什么呢?它就表示啊,我带给对象需要实现的方法。这里边就是你要。通俗来说啊,就是现在我们调目标对象中那个方法,咱现在用method就可以进行调用啊,就是你要调用那个目标对象中的方法,就是方法在里边,我们给它做了一个重写。就是需要重写你的那个目标对象里边那个方法就是第二个。
13:00
通俗说就是可以调到目标对象中的一个方法。然后里边第三个参数。这是什么呢?叫object的数组,它指的就是你那个对应方法中的参数,就是中,比如说调那个相加的方法里边两参数,调减乘除都是两参数,就是麦的方法。里边的那个参数,这就是三个部分,然后咱们最终来写一下啊,咱们看它的具体过程。首先啊,在里边我先做一部分,因为咱们肯定要调这个最终那个目标的方法。啊,就是调用目标的方法,那怎么调用method。里边这个方法叫E,呃,注意啊,这E跟它不一样啊,这是那个调方法的,这是那个E,里边E是名字一样。这你可以理解为调目标方法,然后在目标方法中第一个传入这个代理对象,然后第二个传入你的参数,就这个,最终它有一个返回的结果,比如咱们叫这个result。
14:14
这是我们写到的啊,调这个方法,而我现在要怎么做,在这个调目标方法之前之后我都想做一个日志的输出,那咱给他就最终输出一下,这个输出我从课件中就复制了啊,就是一个简单的输出,比如现在我在它之前做一个输出。就是我们写到的,然后大家看我就把这个方法名字和参数给它输出了。我这里加个注释啊,就是方法调用之前做个输出,然后我在方法调用之后再做一个输出。调用之后再来个输出,这个输出我从里边也给它直接复制过来,就是我们的这个输出。
15:04
最终啊,得到里面这个结果,就是这个result。所以现在啊,把这一部分我们就完成。然后完成之后别忘记啊,把这个咱们需要做一个退。所以现在啊,大家看三个参数,咱们就都准备好了,咱们再重复一遍刚才这个过程啊,然后最终再传三个参数,最后再测试。而我们现在的过程用的是动态代理进行实现,动态代理的特点是什么呢?把我们的日志做统一管理,而不像静态代理那样,我们每部分都需要建这个静态代理类,它里边不需要这么做,而静态代理中它里边并没有做统一管理,这些在动态代理中都可以做到很好的解决。那咱怎么做?我们就是写了一个类,然后在类里边呢,提供了一个返回代理对象的方法,包括把目标对象用构造。
16:01
在创建动态代理对象的时候,我们调里边的new pro方法进行实现,里边三个参数,第一个类加载器,第二个目标对象,所有实现接口的class的数组,第三个invocation handler,就是咱们最终那个实现目标对象那个方法的过程,比如你之前之后输出过程里边有个方法,里边我们在之前输出,之后输出,这里边是调用我们那个具体的方法。这是方法,我们可以列为做了一个重写啊,调这个方法,然后在过程中咱们三个参数就都选完了,最终咱们把三个参数传到这里面来,然后传下啊,第一个类加载器,第二个接口的数组,第三个INC handle,所以现在咱们就把这个代理类就最终完成了,这是用动态代理一个实基于我们的D中的这个对象调里面的方法,最终实现这个过程。
17:05
这各位给他清楚,然后这个完成之后,最后呢,咱们把这个代码,我们做一个最终的测试,试一下最终结果是怎么样啊,那我们来试一下啊。然后这个测试呢,我这么来做,我这里边呢,专门写个测试类,就测试这个计算器这个类。好就叫CL啊,咱就简写了,然后在里边我加上一个问方法,最终我们做一个测试,那咱们看怎么来测试啊,咱们看这过程,首先我们做法就是呢,因为咱有代理类嘛,那我直接就是上这个代理类。计算器最基础的一个实验类啊,把它穿进去。然后大家看现在返回这个就是咱们这个代理对象。
18:03
我这里加个注释啊,就是第一步。我们来创建这个代理对象,咱们是用动态方式进行创建,然后创建之后咱们调用里边的这个方法进行实验就可以了,那我们来调一下啊,在代对象中一个方法get,就得到我们这个具体这个对象。就是这个叫啊,比如咱给它改成我们现在这个具体这个类型,这个计算器类型。变成它啊,咱给它做一个强转。当然这里边如果你是别的类型,可以依次转。我们现在用的是计算器,然后最后调用我们的那个目标的方法,我们来调一下这个方法,咱就一个相加的方法,比如做两个数的相加啊,这个一加二。现在就完成了第一步创建代理对象,得到这个对象,然后调方法进行实现,因为刚才我在里边提供这个返回代理对象这个方法。
19:05
现在完成完成之后我们做一个最终的测试,大家试一下,看一下它效果怎么样啊。我们来看一下结果。然后大家看啊,在前面是不是输出了,在后面输出了,中间是不是咱们的核心业务,你看啊,核心业务中应该就这段话,就做一个相加这个就可以了,那比如说咱可以再试一个,我再试一个这个就是啊,比如咱试一个这个乘的这个操作吧,啊加减乘除咱随便换一个,换一个那个乘的操作就是这个。那我来乘一下,比如说用二乘以这个四。咱们也试一下这个结果。我们来看一下啊,最后这个效果。大家看之前,之后输出了中间是不是核心部分,比如我们现在通过动态代理方式,把日日部分做了一个统一的抽取,方便咱们管理,另外我们做到咱们真正的解耦过程,这就是动态代理我们一个视线。
20:10
所以各位啊,你要理解为什么是代理模式,静态代理和动态代理他们的区别是什么,重点掌握动态代理,因为咱们马上说到A,它的底层用到就是动态代理进行的实现。
我来说两句