00:00
好,那下面呢,那我们再来看静态代理的一些缺点,就为什么我们不用静态代理,对不?我们还要讲一个动态代理,为什么?因为大家注意这个静态代理啊,它确实实现了角偶,这个大家也都能够看出来,你看我们这个现在咱们实现了静态代理之后,你看我的目标类里面,我有实现日志功能吗?没有,但是咱们最后咱们有没有把咱们的日志功能添加到咱们的加减乘除中,有,哎,所以说大家注意,这是咱们的静态代理确实实现了结偶。但是因为啊,咱们的代码是写死的,你就比如说我们的静态代理类实现了跟咱们的目标类相同的接口,第一点写死的,第二点写死的,咱们的这个静态代理类里面,然后咱们所对应的目标对象,然后咱们也是写死的,对不对,所以说它完全不具备任何的什么呀灵活性。你就比如说我现在如果我还有一个目标类,我也要来实现日志管理,我要做的操作是一样的,在方法执行之前输出方法名跟参数,我要在方法执行之后来说出咱们的方法名和结果,那大家说这时候你怎么办?
01:10
你能实现这个功能吗?你通过咱们这个静态代理类能实现吗?不能啊,因为它实现的接口跟目标类是一样的。我们当前咱们的目标对象,它就是咱们的。这个目标目标类类型的对不对,就是我们当前的一个目标对象确定的目标对象,所以说它完全不具备任何的灵活性。对吧,就拿咱们的日志功能来说,将来如果我有其他地方也需要附加日志,那咱们是不是每一个目标类,你是不是都得去创建一个日志功能的静态代理类啊。这个时候咱们就会产生大量的代码,因为大家会发现咱们写的代码它还都是一样的,对吧,我们都要把方法名跟咱们的参数,还有方法执行之后的方法名跟结果输出,所以说就会出现大量重复的代码,日志功能还是分散的,有没有统一管理没有啊,所以说我们现在咱们要干什么,咱们把日志功能就给它集中到咱们的一个代理类中。
02:09
然后呢,它可以针对于咱们所有的目标类,然后来实现咱们的日志代理,OK吧,那这个时候静态代理能实现不能大家注意他实现不了。这个时候咱们就要用谁的呀,就要用动态代理来实现了,好,那这个动态代理大家注意它到底动态到哪了,什么东西是动态的,也就是说我们现在啊,咱们需要实现动态代理的时候,我们并不需要手动去创建这个动态代理类,而是通过我们JDK中给我们提供的一些方法,一些API,然后动态的为某一个目标类来创建它所对应的动态代理类。大家注意,也就是说什么啊,就是说我们现在呢,咱们的代理类我们是提前是没有的,我们需要TDK为我们所提供的API,在代码运行的过程中,动态的帮助我们去创建每一个目标类所对应的动态代理类,所以说这个动态指的是什么?指的是我们会动态去生成目标类所对应的代理类。
03:15
这个大家一定要听,好好,那我们在这咱们该如何去做,比如说我们在这咱们先来创建一个叫做proxy factory的啊,咱们怎么做呢?大家看,然后我们在这咱们直接来new一个class,叫什么proxy factory?董老师为啥要叫proxy factory,这是一个工厂吗?是。大家看好啊,这是一个工厂类,为什么说咱们咱们说这是一个工厂类啊,那是因为我们当前咱们创建的这个类是真正的代理类吗?不是,而是我们去动态生成目标类所对应的代理类的一个。就相当于一个工具类。能听懂吧,也就是说这个类本身是没有什么功能的,这个类它本身呢,它并不是我们某一个目标类所对应的具体的代理类,而是我们可以通过这个类帮助我们动态生成这个目标类的代理类。
04:10
这个大家注意,所以说咱们把它叫工厂对吧,咱们把它叫工厂,因为这个东西它专门帮助我们去生产代理类的,OK吧,这样的啊行。那下面呢,我们再来看,那我们现在大家说我们是不是要知道咱们的目标对象是谁啊,对吧,所以说我在这需要去创建一个目标对象,那这个目标对象大家想想,因为它现在是针对于任何的目标类来创建代理类的,那所以我们在这儿咱们的这个类型咱们写什么,也就是说我当前目标类的类型确定吗?不确定,不确定怎么办?那就是object呗,大家说是不是target的T行,OK,然后下面同样的操作,创建一个有参构造来为咱们的目标对象来进行赋值。然后再往下,大家注意啊,那在这呢,那我们怎么写,因为它是个工厂类,再说一遍,这是个工厂类啊,它是能够帮助我们生产目标类所对应的代理类的代理对象的,知道吧,所以我们在这儿创建一个方法,然后这个方法返回值是啥?因为我们也不知道它的代理对象,它的代理对象到底是什么类型啊,因为这是动态生成的,你能决定这个类叫什么吗?咱们决定不了。
05:26
这是当前咱们代码运行的过程中动态生成的一个类,OK吧,所以说返回值还是object,咱们叫什么?叫做get proxy OK,然后大括号大家注意啊,那在这呢,我们来使用的这个动态代理的方式,然后叫做什么?叫做GDK动态代理,大家注意啊,叫JDK动态代理,所以说我们来使用的这个API呢,大家看,那咱们在这就直接return呗,咱们所使用的一个类叫做proxy,叫做proxy在哪呢?在我们当前咱们的反射这个pro下面的看到没?所以说它其实就是通过反射来实现的动态代理,OK吧,然后proxy点。
06:09
里面有个方法叫做new proxy instance new创建proxy代理instance实例,来创建一个代理实例,我们就是通过这个方法,然后来帮助我们创建的动态代理类动态代理对象,OK吧,好,那大家来看这个方法里面它一共有三个参数啊,这三个参数大家一定要好好听,一定要知道是什么意思啊,首先呢,Class loader,然后第一个叫做class loader叫做类加载器,然后第二个叫什么?叫做interfacece interface是接口的意思。然后呢,这个是咱们的什么呀?叫做interface参数名叫interface,它的类型是一个class类型的数组,然后最后一个是一个什么是一个对象,叫做invocation handler,那咱们就把这三个参数分别跟大家说一下啊,首先第一个叫什么叫class loader来咱们这样啊,然后咱们把这个方法给它点开,然后把这三个参数给它复制过来,然后给它放到这个位置杠星星来。
07:15
大家看啊,一共是这三个参数啊,咱们就留一个参数名吧,啊,或者说咱们就这样去写啊,这是第一个。啊,然后来这是咱们的第二个参数,然后第三个参数,大家看一下啊,第三个参数,然后是它啊,然后这个咱们把它给干掉啊,把这个泛型给干掉,行就这三个,首先第一个叫做类加载器,那为什么它需要在这传过去一个类加载器呢?大家注意,因为这叫什么代理,这叫动态代理,那所以说我们当前咱们的代理类它是动态生成的。也就是说在我们当前这个方法执行之后啊,它是会帮助我们动态生成一个类的,但是大家都知道,那我们现在这个类是什么类,叫做代理类,那我们现在咱们的代理类,我们说过类你要想被执行,那就必须要先被加载,而类的加载就要经过咱们的类加载器的加载,对不对?所以说因为这个类是动态生成的,所以我们必须要指定一个类加载器去加载当前这个类,我们才能够去使用它。
08:25
OK吧,好,所以说在这大家看好这是什么意思,然后咱们在这儿来指定,哎,我们要做的是来指定。指定。指定对吧,然后来加载,然后咱们动态生成的这个代理类,代理类的类加载器类加载器类加载器器,OK啊首先大家注意第一个参数是指定加载动态生成的代理类的类加载器,好,那这个东西咱们应该怎么写呢?大家想想。
09:01
啊,首先呢,这个类加载器啊,咱们提到这个类加载器了,那咱们就来回顾一下,咱们的类加载器一共有三种,首先第一种是啥啊。第一种是不是叫做根类加载器?对吧,第二种叫做扩展了一家百气。然后第三种呢,叫做什么应用类加载器,最后一种叫自定义类加载器。一共有这四种,首先第一种根类加载器,它的底层是用C来实现的。对吧,然后咱们获取它的时候,它主要来加载的是我们当前的一些核心类库。然后咱们的扩展类加载器,然后它加载的是咱们的扩展类库,然后我们当前咱们自己写的这些类,或者说是我们引入的第三方价包里面的类,它都是由咱们的应用类加载器加载的。OK吧,那所以说大家想想,我们现在要想加载咱们动态生成的代理类,这个时候咱们找谁呀?你找应用类加载器就行,那应用类加载器咱们怎么获取呢?大家想想类加载器这个怎么获取?类加载器大家应该都知道是通过反射获取,咱们只需要来获取我们当前某个类型的class对象,咱们直接点get class load就可以获取类加载器了,这东西简单对吧?那所以我们现在要想去加载它,那我们就要用到。
10:23
应用类加载器,那所以咱们随便去找一个类。获取它的类加载器,是不是都是应用类加载器啊。啊,我说的是我们自己写的这些类啊,大家随便去找一个,然后它就是咱们的应用类加载器,OK吧?啊,所以说在这咱们怎么获取,大家看啊,比如说我来获取加载咱们当前xy factory这个类的类加载器,那所以说怎么写啊,是不是叫做proxy,然后factory.class.get class load,你或者说咱们当前这个类里面,咱们直接一个this表示的是不是就是当前类的对象啊,点get class,再点get class loader OK,大家注意,这就完事了。
11:07
知道吧,啊,这是咱们的第一个参数,好,咱们把class load给它放到这,好下面咱们再来看第二个叫做interfacece,这东西是干什么的?那我们当前你不管你用动态代理还是静态代理,咱们的思路是没有变的呀,我们之前在讲静态代理的时候,咱们说的你的目标类要跟代理类来实现相同的接口,那所以说大家想一下,我们现在要想来创建一个什么叫做动态代理类,动态代理对象,那我们当前的这个对象,它所对应的类啊,也就是我们要动态生成的这个类,它是不是必须要跟咱们的目标类来实现相同的接口,对不对?对吧,因为咱们静态代理里面去这样去写的呀,对吧,这个时候咱们才能保证你的代理对象跟咱们的目标对象实现的功能是一致的。OK吧,所以说这个是干什么的,大家注意,然后来获取,然后咱们的目标对象啊,然后实现的所有接口,实现的所有。
12:12
实现的所有的接口的class对象的数组,大家看,因为这个方法的返回值不是一个class数组吗?好,那这个东西大家应该都都会获取到吧,这也是怎么获取的,通过反射来获取,首先咱们的目标对象叫做target,然后呢点大家来看在这是不是有个get class方法可以来获得目标对象的class对象,然后下面咱们再通过点叫做get interface就可以来获取我们当前某一个类型所实现的所有的接口的class对象所组成的数组。能看懂吧。OK,然后下面大家要知道为什么要获得这个,为什么要获得它实现的接口,这个的class对象的数组啊,你一定要看好为什么要获得它,因为我们从静态代理,咱们写到了动态代理,静态代理里面咱们就说了,你要保证目标对象跟代理对象实现的功能是一致的,那所以说我们当前怎么从代码层面,怎么表示你的目标类跟代理类它实现的接口要一样,OK吧,好啊。
13:22
好,然后下面呢,咱们再来看第三个参数啊。
我来说两句