00:01
好,我们接着前两期的内容,把剩下的一丁点内容。完分享。呃,前两期呢,分享了这个策略模式的实现。啊,解决这个登录啊,登录这个六种方式,然后怎么来通过策略模式来。解决,然后通过引入策略模式的同时呢,引入了我们那个SPI的概念。呃,前两期已经讲过了,JDK自带的S和spring这个结合的那个SPI。然后把这个啊,登录的这个方式把if给它去掉了。然后呢,就是。上期讲到这个spring factory的这个方法的时候,我们自定义扩拓展了一个。啊扩展类,然后实现了通过一个class和它的这个呃,加载器,然后获取到指定的这个。
01:05
啊class啊,指定的指定的病去,呃,通过指定的病去调用它这个log in方法。嗯,但是这个有个问题就是说。啊,有人反馈过这个spring factory loads,这个你加载的时候,它不是只加载了,就是你在。这个下面配了两个四类。那么它真正调用的时候呢,我们重启再尝试一下,然后再。把这个接口打开,调用接口打开。嗯。就是说当它真正调用的时候,一调用了两个log in的那个方法对吧。呃,就是说当我们。调用的时候完全可以。判断它判断一下它的这个type对吧。
02:00
这样就能够实现最终只有一种这个一种一种登录方式的这个调用。用这种方式是吧。然后才启动完毕是吧。哎,那它调用成功了之后,是不是指对吧,如果我们在那项列里面,通过判断它登录类型的这个方式。啊,然后也只实现了,虽然我们在factor里面配置了两个动态的一个B啊class实现类,但是真正当它调用的时候,它还是判断这个入参啊,最终只调用了一种实现方式。呃,这是实现的这种一种方式,对吧,一种方法,但是如果你这么判断的话,即便是我们SDDK的这个SPI,它也可以执行。啊,但是我想要的效果是什么呢?尽可能的不在我们的这个子线位里面写任何判断的。
03:03
方法,除了业业务逻辑之外的判断方法。尽可能当它调用的时候啊,就只调用一个时间类,虽然在前面我们这个配置项里面已经配置了多个,对吧,但也希望在它调用的时候只调用一个。把所有的这个调用方法都在这个,呃,获取实现类的时候,就能获取到指定的实现类啊。然后呢,这个spring的那个SPA呢,有一个什么问题,就是说对吧。呃,他他的这个load factory方法呢,我们可以到最后看一下有什么问题,刚才我们不是。加载的时候没有问题对吧。啊,我们我们再再调一下。他就要用了两种方式没有问题对吧,但是当我们把这个这个我们应该以前。前面的视频忘记了有没有。
04:00
讲过是吧。当我们在他的这个B里面调用了一下这个map方法,查一下当前用户下面所有的用户,啊,调了一下数据库。啊,就是这么一个操作,大家会有什么问题对吧,然后我们把debug放到这里。然后我们开始调用。会发现一个什么问题?对吧,把它给8UG放掉,会报一个控制针对吧,也就是说当我们,然后我们看一下它。调的这个。调的的这个方法,就是说调到这一行的时候,32行啊,他报了一个user map为空,然后往上翻一翻,对吧,它有一个springd的一个引爆和方法啊。啊,它的这个invo方法啊,调到里面啊,最终调了一个invoke方法。
05:00
但是从表面上看啊,它调的好像是spring那个管理的这个C里边的对吧。最终出来一个。报错。但是呢?呃,实际上。实际上它那个EVO方法相当于啊,相当于重新拗了一下这个病啊。导致呢?他获取的病。他获取的这个user map这个病。它不是性管理的这个病啊,导致它最终这个map相当于new了一下,所以说它用出来之后,它相当于not not调用这个。呃,方法的时候报了一下空间对吧,这是。呃,Spring factory这个一个。缺点啊,也不算缺点,毕竟他有这个解决方式,不算缺点是吧。就我们使用不当造成的。那么。我们有没有什么方法对吧,能够调用它的同时。
06:02
第一,不写if语句,在我们的实项里,里面不写依附语句。第二呢,能够调用spring管理的这个B,对吧。有当然是有的是吧,那就是什么呢?就是我们在这个笔记里面。往下翻一翻。呃,了解完spring这个factory的方法呢,有一个叫做application contest,它加载的时候呢,啊,它就可以对吧,获取到spring a op管理的bin。啊,管理的病,然后我们往下翻一翻是吧。在这个位置上面已经写到了,就是呃,网上的一个spring启动一个流流程对吧。然后它实例化里面有个调了,调了在我们那个run方法里面有一个refresh contest的方法,对吧,它里面呢,在加载这个并的时候,能够获取到这个实例化。
07:05
这个spring管理的病,然后通过这个这种方法,然后我们看一下怎么写是吧。所以我们昨天对我们那个输入了一个,在上面输入了一个application。它获取病呢,就是这两个两种方法,一种是b name啊,一种是指定你需要的类型啊。还有这下面的就不看了,都差不多对吧。你呢?然后我们提前不是用那个动态枚举维护了一个。对吧,他这个。策略媒体啊。就是这个,就是有一个。但是class啊,过去到了它。然后通过。嗯,通过这个application contest,然后他再调用一个。那个。
08:02
在那看到个语方法把。看它能不能实现对吧,然后返回一个。负值对吧。那我们启动重启一下。那我们逮个bug吧,对吧,因为因为什么呢?因为这个刚才介绍这个applicationfflic context的时候啊,这个。Spring的启动流程调用方法啊,它有一个创建application contest,然后当它调用完refresh contest的时候啊,它在里面会加载一些并refresh方法。然后我们可以看一下源码,它都干了一些什么东西是吧。呃,准备一下预加载对吧,加载配置类啊,工厂这些所有的加载方法都在这个里面了啊。但是呢,我们可以给bug跟着走一下,但他我们这个。
09:01
呃,提前想要加载的这个病在什么位置出现对吧。稍微有点慢啊,稍微有点慢。当他调用factory这个方法的时候。啊,把它调完。那我们看一下bug有没有个方法。那在这里就要完了,对吧,我们看一下。里面有一个啊。
10:01
Contest,它这个病都在这个factory里面,然后其中呢,这里面有一个。Forz病啊,叫做冰冻的啊,冰封的病的定义内容啊,我们看一下这里面有没有是吧。这里很快就看见这个第12个和这个十三十四个对吧,都是我们。需要加载的病啊,这个被spring管理的一个病,对吧,都已经出现在这里了,对吧,这三个都都都是有的。那么在我们真正。需要这个程序需要获取的时候呢,哎,它可以直接通过这个get b get b方法啊,我们。有一些bug。哎。是不是我因为我们那个忘记注这个注释了是吧。这个factory这个忘记注释了是吧。然后它那个还是报那个。
11:01
控制针对吧,这样我们能能对比一下对吧。刚才没有注释的时候,他报了一个控制针对吧。那我们现在把它放开了。他报的不报了,对不对,不报了。啊,能不能证明呢,能不能证明第一呢,就是说我们在加载的时候,Contest的时候,它里面有我们想要加载的B。其次呢,当我们获取病的时候,嗯,在get b的时候呢,它获取了到了动态我们指定的这个病,并且我们没有写if附方法,并且在我们这个第一第一个这个账号密码登录的时候呢,它获取了所有的用户名,这个所有的用户,当前这个数据库里面所有的用户啊。我们可以把日志加载到这儿。这个看一眼啊,就是一个非常简单的一个。数据库。非常简单的一个。
12:14
那个。诶。这个方法突然,突然之间。啊突中间不是突然间忘掉。刚才突然突然之间不知道想什么,忘掉了。我们再重新请求一下好吧。看一下它里面的那个。
13:00
就是一个创建名,创建人创建时间ID啊用户名密码对吧,就是一个简单它打出来了是吧,他查询数据库的时候呢,它调用了一下spring管理的B,但是呢,它并没有报控帧对吧。那么就是把这个application contest呢,它就解决了这个啊,Spring factory这种获取的方式。啊。那个并且这个它加载都是在启动的时候加载的,并且这个contest的方法,它不需要去配置啊,配置你这个加载的宾只需要标识注解之后呢,你想要加载哪一个啊,你就去加载哪一个就好了,对吧。然后呢?呃,这个application contest呢,简单我们讲了一下,解决了一下这个方法是吧,它最终在使用的时候呢,调了这个refresh方法啊,调用这个finish factor initial。
14:02
啊,最终把我们的病啊,这个叫做。For reason就是冻结了所有的病,对吧,通过这个嗯方法它获取到了。那么这个。既然讲到这里呢,我们最终最终还只剩一个double的SPI,对吧?那么double的SPI它跟这个spring和JDK的S有什么区别呢?就是说我们不管是spring的还是JK的第一呢,我们都需要配置啊,啊都需要配置。第二呢,都需要在都是在这个像spring都是在它容器启动的时候就已经下载了。但是有一个问题就是说假设这个场景。他不是很常见。啊,它没有就是说呃,你预先加载过之后,我有可能不用,我也有可能用对吧,那么我当我出现有可能不用的时候呢,你提前加载好了之后。
15:04
那是这,这就是对一种对资源的浪费。那么其次呢,就是说它没不不能实现动态加载,并且指定名称的去加载,对吧。那么。Double的SPI呢?它为什么废弃这种spring的SSP不用,而自己去实现一套,那么他想要解决的和想要实现的这种方案就是它的这个。啊,S的一个。优点。就是它通过配置文件,也是配置文件去动态加载,在提前加载好之后呢,就是说。它会根据你什么时候想要啊,什么时候想要用啊,他才会加点药啊。他说了一下这个double的这个特性,我们可以看一下这个。这个是新版的啊,这个是旧版的,然后看旧版的也可以对吧。
16:01
他说这个SPI啊,PI在我们这个拓展wpi的这个概述这里啊。可扩展性的优点就是表现出模块之间结耦啊,符合开立原则,对扩展开放,对修改关闭。当系统增加新功能的时候,不需要对现有的结构代码进行修改,仅仅新增一个扩展就可以了。那么它这个SPI之所以叫做拓展,叫做extension logo的这个。啊,命名方式就来自于这对吧。那么它的SPI呢,就是为了加强D的API啊而来的。那么它的这个就是说他说有什么缺点JDK是吧,如果这个拓展点加载失败了,那么拓展展拓展点的名称都拿不到了啊,还是有这些缺点啊,有资源浪费啊,没用上呢,加载了啊会资源资源浪费。
17:03
并且这个大根据它这个拓展还做了一些很多很多很多的这个协议的实现啊,自定义协议啊,自定义协议过滤过滤器路由的所有的这些实现都是基于这种方式啊,非常非常的nice。好吧,这个直线方式非常的优雅,并且它在获取的时候呢,能够指定。B的这个name来获取啊,获取它的这个词签。嗯。然后我们那个这是这是一个源码的一个地址啊,我们把这个。源码我可以打开一下,然后把它下载下来,然后看一下它里面SPA对吧。它有一个实现了一个核心类extension啊。这个有点慢,稍微有点慢是吧,我们看一下那个。
18:03
呃,看一下PPT上面对吧,这个。PPT上面那边有一个事例叫做extension loader啊,点get extension loader,把service传进去,返回了一个loader啊,当那个loader调用那个extension的时候,你把实现类的名称。那我们这个实现类的名称呢,就可以通过动态枚举的方式把它提前绑定好,对吧,把它提前绑好。动态美女的这种方式,把它提前绑定好啊,然后也可以获取到对吧。然后你就可以去做一些事情了啊,他这就是他的一个实现方式。呃,加载下来了是吧,你就。拉一下,拉一下这个人。
19:08
嗯。已经存在了吗?我觉得我们找我拉过了,我之前拉过了,那我们就直接打开了。直接打开它这里有一个extension对吧。我想要看的就就是这个,就是这个。然后他这边,嗯,有这个,它就存在于这个。嗯,案例里面。然后把这个我们主要是看到它的源码。他。下载一下。对比一下。
20:08
天上山下的。它这个load就是它的一个核心实现类啊。就是在这里。它读取呢,也是made in下面double文件夹下面的这个啊主线,然后它通过这个权限令类名的方式,然后去搭配的去配的这个。对吧。简单看一下啊,还有一个漏的方法。Tension的这个方法啊。然后呢,它输入的这个名称呢,就是你拓展类的这个名称,对吧,北京的这个名称,然后它还可以传一个布尔兹,其中获取的呢。通过调用这里去获取的是啊。
21:07
这就是他这个核心的直线,那么它这个实线呢,还需要搭配一个注解。叫做。呃,假设它就是对吧,它就标识了它的SPI啊,它就有这么多。这么多的一个时间对吧。不同的时间。啊,它在应用的时候。看一下它的应用。
22:09
我记得是有一个示意的。算了,我们就先不找了,今天就不先不找了,对吧。嗯,回头我们那个有兴趣的可以把这个源源码的地址拉下来之后呢,自己去看一下是吧。然后它这边呢,这个应用手册里面讲述了它那个加载流程啊,都官网的非常的详细,然后就是这里。它的一些拓展啊,协议调用啊,监听暴露对吧,所有的的这些实现啊,所有的这些实现都是基于拓展能力去拓展的。就是这些协议,那么它其实跟我们的这个application contact的啊是有区别,但是获取的方式是差不太多,对吧,都是通过这个病病的这个name就获获取到了啊。
23:03
那么到此为止呢,我们所有的这个S的这种实现方式,那么可以讲完了。就讲完了。那么呢,我们还有一个新的拓展的拓展的地方。就是说。以上所有的这种实现方式,我们提前都是通过对吧,一个叫做动态枚举,通过一个枚举类去维护了它这个登录方式和它实现类这个class之间的那个关系。那么,如果我们。以后有新增人脸识别啊,指纹登录,微信登录这些所有的方式的时候呢,我们还需要对吧,提前维护好一个这个枚举。当然维护一个枚举的成本很低,对吧,提前维护好了,我们在写的时候业务的时候,这个啊维护一下就可以了,但是能不能有没有一种更简便的方式啊,更简便的方式。
24:02
啊,具有。只需要这个。再比这个枚举再简单一点的方式去维护他们的关系呢,啊,当然也是有的啊,就是我们那个拓展的地方呢,叫做。注解驱动啊,根据注解去获取。啊,在我们那个加载,加载我们那个bin走变的那个bin这个run方法的时候呢,有一个叫做根据条件获取这个组件,它有一个方法。对吧。嗯。我们简单要看一个啊。这个方法啊。它呢,调用了一个SC,这个SC他扫描了一下,它这个解对吧。然后获取了这个原注解的一个读取对吧。啊,在这里获取了一下。然后最终呢,调用了一个。
25:00
呃,最终调用的这个。就是能够获取到啊,这个他判断了一下,用instance of判断一下是不是注解的一个病,然后来获取到,也是获取到这个b name对吧,然后通过这种注解的方式,然后能够获取到。嗯,根据一个注解驱动。那我们新建一个什么东西呢?新建一个动态枚举的一个注解,叫做dynamic handler type,这已经提前建好了。然后呢,他的他的一个。啊,它的一个返回值就是一个枚举啊,Handle了是它一个实现方法啊,通过handle方法啊,标识它是一个。动态媒体的一个注解啊,标识我们的一个账号密码呢,是一个账号密码登录啊,标识它一个。账号密码登录啊标识我们那个是一个验,这个是一个验证码登录吧,通过这个注解来标识。
26:00
然后当我们怎么使用呢?当我们调用的时候,也是通过一个out啊,提前先维护一个媒媒体关系是。枚举和service之间的关系有一个map。这个map呢?他通过outwe把我们所有的动态这个login service的一个list拿到,然后他去便利,便利维护了一下这个K,就是这个注解。这个关键这个方法就是a notation u,它获取到这个handle,这个获取的这个方法,然后这个注解呢,就是这个dynamic handle type。通过他的这个handle的方法,当做返回了一个dynamic,对吧。然后V呢,就是它这个service实现类啊,那我们实现应用的时候是怎么用的呢?我们在这里。Map里面直接获取一下啊,Map里面直接获取一下。
27:00
我们看一下。通过map get一下这个na啊,这个里面获取了它的名称对吧,然后把它这个type做了一下转换,就能够获取一个service啊,然后我们再重启一下,看看能不能实现。能实现吗?能实现对吧,它这个。调用成功的,并且它这个里面也是使用了这个。啊,并并里面那个spring管理,并且没有报错对吧。那么这种注解驱动的方式好在哪呢?就是你把每一个以后再新增任何一个病啊,你只需要你你反正也得写直线啊,直线你你不可能说直线都避免不了,对吧。当你写这个实线的时候,只需要标识一个注解,然后在它启动的时候,它就维护好了。这个。
28:02
注解跟它那个时间类之间的关系,当我们使用的时候啊,直接get就可以了。啊,非常的简单,也比这个维护枚举呢稍微简单了一些,只需要加一个注解对吧,一次维护出口方面。嗯。然后这里面简单讲了讲解了一下这个步骤,就在这里面对吧。最后呢,我们还有一个点,还有一个优化点。就是现在呢,我们呢。确实所有的这个不管是消灭if这个目的也已经达到了,对吧。他通过通过动态的这个名称去获去获取这个class对象,它也达到了。啊。就调用那个STEM管理的病呢,也没有报错,我们所有的目的都达到都达到达到了对吧。但是呢,考虑到一种场景,就是当我们把类似登录业务的场景提供给第三方啊,上游或者是下游的这个业务去调用的时候。
29:09
当它同时调用我们的这个方法啊,传过来不同的参数,但是在上游是由于一个接口。交交,比如说上游写了一个service啊。Service。教练。他同时。调用了七种实现,当然它不是同时调用啊,它指的是。通过不同的业务去判断啊,他调了七种。那么一次性调你七种呢?你需要循环对吧,它需要循环,或者是你需要循环啊。或者是他需要写。其次。对不对。那么有没有在这种业务场景下去优化我们的这个接口啊。那么就是我们下面写的这个。
30:02
Complete future啊,通过一个异步获取的一个方法。然后来加载,哎,我们的这个map里面的这个,然后去获取。呃,他会。返回一个布啊。挽回一个啊。
31:00
然后通过这个future呢,可以获取啊,对吧,Get里面的所有的东西。啊,关于盖什么也好,对吧,我们类的future啊。这种方式呢,他也能够实现,它的这个优点是什么呢?它通过加载线程值去异步的执行我们这个方法。啊,异步的去执行。呃,这样呢,它能够比我们在这个原有的基础上更能够性能更会提高一点啊,异步加载可能更能够提高一点。嗯,像我们那个特别调用脑梗炎的时候。上面呢,加载了一个这个线程池,一个基本的一个线程池,非常简单。然后我们看一下他这种方式能不能实现。啊,这这样,因为业务比较简单,不是很复杂,没有写任何的这个业务,所以说它实现的很快对吧。那么到此为止呢,我们就所有的。
32:03
嗯,包括我们这个PPT录到这对吧。那我们那个所有的这个。策略模式搭配这个SPI啊,来解决,遇到我们这个if else啊,我们所有的这个。呃,知识分享呢,就完完成了。在我们那个。做以后提供外部接口的时候呢,我们都可以提供采用这三种方式啊,甚至是四种方式,五种方式的其中一种去解决我们的这个,你觉得哪个简单,哪个方便,哪个维护成本最低。啊,你就用哪一条。啊,去维去去做你的这个接口啊,去维护一下,优化一下。那么如果大家有需要这个PPT啊,或者是这个代码源码这个文档的,我会导出一个PDF格式,然后就联系我获取一下就行,嗯。
33:02
好吧。好的,谢谢大家。
我来说两句