00:00
好,来说第三小节,自定义start,我为什么需要自定义start来参照spring BOO官方文档using spring boot,这有所有的starters所book未来简化开发咱们常用场景的这些场景启动器都给我们抽取出来了。当然呢,即使是这样,所有的starters也不能模拟我们后来的所有开发场景,比如呢,我们现在有一块功能我们非常常用,我呢把它抽取出来,其他的模块呢,要经常引用,而且呢,引用过来要一切场景都自动配置好,那此时我们就需要把这个功能我们也抽取成一个自定义的start,别人呢,一引录自定义的start,所有东西全备好,你只需要改一下配置文件就能用,我们也需要我们能做出这么一个效果,那自定义start要做出来呢,我们就需要对s boot底层的start原理非常清楚,前面呢我们已经分析了非常多的原理了,在这一块呢,我们就直接来捋一下,前面的这些原理呢,我们已经都在自动配置原理章节都已经串过了,好,那首先呢,第一个原理我们想要让别人来。
01:00
引入我们的场景,首先我们得有一个场景启动器,类似于泡沫里边我们想要web开发场景,我们就得有一个场景启动器,而这个场景启动器呢,有一个特点,点进来,来找一个这个start web。Start web这个场景启动器呢,大概大家打开发现里边呢没有源代码,所以呢,一一个场景启动器默认呢,一般只是来说明我们当前场景里边有多少的依赖,把它依赖引进去,而对于某一个场景真正的自动配置功能往往是在这一块,我们来参照spring部的start test里边,在test里边呢,专门会有一个叫boot test的auto,所以呢,我们在这抽取的时候,我们也这么来做,我先来编写一个start,这个start呢没有任何代码,只是用来说我们当前场景要引入哪些依赖,然后呢,这个start同时呢,引入了我们的当前场景的真正的自动配置包,而自动配置包呢,就要引入我们spring boot最底层的每一个模块,都要用到spring boot starter这个包就行了,那我们的这个自动配置呢,就可以写好了,那就基于这个原理,我们先来创建上两个项目,我在这儿专门来创建上一个工程,你们要创建多个项目,我在这儿创建一个工程,我选中呢?
02:12
它这个空工程的方式,它呢可以容纳多个项目,我们叫boot,那这个零九吧,我们自定义卡特,那我们的这个start好,我们自定义的start,这个零九好,我们准备了这么一个项目,我们自定义start,这个空项目呢,我们先来创建出来。然后呢,我们在这个空项目里边,我们来添加上模块,首先第一个模块是我们的这个场景启动器,我们现在呢,以ma模块为例,我们就叫com.at硅谷,那我们场景启动器的名字呢,我们就叫hello,我们的这个an硅谷,Hello spring BOO start,这个场景启动器的作用呢,非常简单,它里边呢没有任何的源代码,只是呢给我们说我们当前场景需要引入哪些依赖就行了,好,那点一个分类式,所以呢,接下来我们所有的自动配置功能,我们还得有一个我们的这个,呃,这个包,这个包呢,我们使用M的初始化向导来做,我们就叫com.at硅谷,那这个包呢,我们一般名字我们可以叫an硅谷,Hello,我们的spring book start,我们的这个auto con就是我们的自动配置包。
03:23
那这个自动配置包里边呢,就给我们做好了所有的自动配置功能。来选中一下,好,我们现在呢,也无需选中任何开发场景,我们现在只是要做一个自动配置包啊,来准备好,来点来点一个OK。好,那现在看我们的这个效果,我们这呢有一个场景启动器,这个是未来让别人引用的,所以呢,我们这块功能的自动配置都在这个auto康菲包下,所以我们这个场景启动器,首先它要做的第一件事是dependences,它来引入我们的这个自动配置。
04:00
把这个自动配置的这个这一块拿过来,我们来到我们的这个start里边,比如说别人只要一有我场景启动器这个自动配置包就进来了,那我们对所有功能的自动配置就写在这个项目里边,好怎么写呢?我们再来看梳理一下我们之前的源码,在这个自动配置里边呢,他还给我们引了单元测试啊,单元测试这些我们都不要了,包括这个插件我们都不要,我们这个项目呢,不启动,不单独打包,所以呢,我们把这个自动配置包里边没用的东西把它删掉,然后呢,我们包括把它的这个配置文件也删掉,主程序我也删掉,没啥用,好,那现在呢,我们这个自动配置包在这已经有了,我们启动器引入自动配置包,那我希望呢,有一个功能场景能自动配置,什么功能场景呢?假设我这有一个业务逻辑组件service,它呢叫hello service这个组件啊,经常使用,所以我把它功能抽取出来,这个组件里面呢,有一个方法,它。
05:01
哎,比如呢,我们叫say hello,方法我们给人呢要打招呼,你给我传入人名,我就给你打招呼,但打招呼的时候呢,我有一个礼貌用语,那前面这个礼貌用语呢,有一个前缀,有一个后缀,所以我们希望最终打招呼呢,是前缀加上冒号,加上我们当前的这个用户名,再来加上我们打招呼用的后缀,好把这个后缀呢再来加上SX,而这前后缀呢,我们又不是固定的,我们希望是可配置的,所以呢,我专门再来准备一个。按照我们以前,我们可以把所有的配置更某一个属性文件绑定,所以我们现在呢叫hello proper practice,那这个属性类,这个属性类呢,我们可以来写上一个注解,叫configuration pro,这都是我们以前用的,它呢绑定配置文件里边,比如我们以硅谷第二哈开头的所有配置在它里边呢,我们有两个属性,比如一个加prex好我们的前缀,还有一个是我们的后缀,好我们把这个前后缀呢,我们可以来get set方法来给他拿到,那这呢就有一个属性类,所以呢,你想要打招呼,我们把这个属性类呢,也放到某一个包下。
06:25
你想打招呼到底用哪个前后缀,这个不是你来决定的,你应该把这个属性类呢给我拿到hello properties hello properties,然后呢,这个属性类我们希望它自动注入进来,然后呢,再接下来我们从属性类里边点一个答get,把它的这个前缀拿来,还有属性类里边把它的后缀拿来,好,那我们这个hello方法呢就做好了,注意我这个hello service呢,我没给容器中放,这个默认不要放在容器中,因为我们要配置默认不要放在容器中,我们这个组件呢,还不一定要给你容器中放,所以我们不写这个service,默认不要放在容器中,那我们怎么办呢?我们专门来写一个自动配置类来完成这个事情,所以呢,我们在这个O包里边,我们比如呢,我们就叫一个hello service自动配置,别人呢想要引用它,我们希望呢,所有功能是自动配合的,Auto con好。
07:24
那这是它的这个自动配置类,那这个自动配置类呢,我们一般名叫auto configuration。这块呢叫auto conf RA,好,我一般叫它,我们把这个名文件名呢重新命名一下,然后我们来说这是一个配置类啊没问题,然后呢,接下来这个配置类里边呢,我们可以给它容器中放一个组件public,但是配置类呢,我想要放组件,它不一定一定要放,所以呢,我们还可以模拟我们以前看过的源码,有一个叫conditional on missing being,就是呢,你容器中没有什么东西的时候。
08:01
Condition的啊,Miss being,然后呢,当你容器中你没有配hello service的时候,我呢,这个配置类才给你生效,我在帮你给容器中放一个hello service,我们来at being,我们使用at being的方式放return,我们想要放hello service呢,那就拗一个hello service。你把这个hello service拿过来好,那我们给容器中放了一个hello service,但是hello service呢,它又跟我们一个属性文件里边绑定的,大家注意啊,它呢是自动注入我们的hello properties的,所以呢,我们现在呢,还要需要一个注解叫enable configuration properties,相当于我们开启属性文件绑定功功能,把hello properties这一块呢给它放进去,那这样的话呢,Hello properties自动就会跟这个配置文件进行绑定,绑定完了以后呢,它还会默认放到容器中,我们说这有两个功能,默认我们这个组件还会放到容器中。
09:04
这都是我们以前讲注解的时候说的,放在容器中好,那接下来呢,我们就这样,我只要创建了一个hello service对象,这个对象呢,只要一放在容器中,然后呢,它需要自动注入,那这个hello就自己进来了,然后我们这个say hello方法就能拿到它的X和surfacex,好,我们把这呢就写好了,这写好了以后呢,我们可以非常简单的把它来进行打包。好,我们使用me,那我们的这个starter,我们的场景启动器要依赖我们的这个自动配置包,所以呢,我对这个自动配置包我先来进行打包,打包呢我使用可令隐掉,现在把它安装到我们本地仓库里边。他的这个生命周期可定,因此好把它安装到本地仓库。我们的这个自动配置包,我们先把它放到本地仓库里边,好放进去了,然后把我们的官方ER,哎,我们自己写的这个starter,我们再来放到我们的这个那仓库里边,Clean clean in install。
10:10
那放进去以后呢,别的项目就可以引入了,好我们专门来准备一个别的项目,好我们再来创建一个项目,比如来创建一个项目,那么这个项目呢,是我们的开发场景com.at硅谷,硅谷,然后呢,我们别的项目呢,叫比如我们就叫BOOT09,然后呢,我们这个hello test hello,好第八。这个拿过来,来点一个next来选中web开发场景。走点一个finish,所以呢,别的项目我们来开一个新窗口,我们来对比,那这个项目呢,想要用我们的hello service,其实他要做的呢,只是在这写一个depend,依赖依赖谁呢?我们这个hello service已经在我们的仓库里边了,我们依赖hello service的这个start。
11:08
所以我们把它的这个start,这是这是它的官方的我们写的场景启动器,我们把这个场景启动器一引入,那只要这个场景启动器引一引入,来刷新来看一下啊,接下来我们的这个hello的这个star引入了,我们就自动配置包也引入了,那自动配置包一引入,那接下来最重要的就来了,自动配置包一引入了以后呢,接下来他就要启用我们的这个自动配置类,将我们的容给我们容器中,把这组件放进去,但这个自动配置类呢,又不可能默认生效,因为生效的规则呢,我们以前说过一个一处源码,就是呢,它会检查Meta info下spring factor里边指定的所有类才生效的,比如我们来到我们以前默认的这个里边,好,我们以它为例,我们的web场景,你想要加载所有的自动配置是在这儿的,我们分析一下官方的在这一块,它呢是默认读取Meta info factory下enable auto configuration指定的这些类启动呢,才加。
12:08
在所以呢,我们的这个自定义start最核心的关键就是当你把这个自动配置类写好以后,你一定要准备这个事情,你先呢得创建一个Meta info文件夹。在类路镜下创建一个Meta INF文件夹啊,前后空格没有没问题,然后呢,这个文件夹下有一个文件叫spring factor,在它里边呢,来进行指定。指定我们的这个自动配置包,项目一启动以后呢,加在哪些,怎么指定,那就参照原来的写法,把这一块呢,直接复制过来,CTRLC来到我们的自定义start里边,相当于enable auto configuration,项目一启动呢,我们要加载哪个包,哪哪个自动配置类,我们把这个呢,自动配置类放在这CTRL位就行了,好,那这样的话呢,我们把这样重新来打一个包。
13:01
我们的这个官方start没变,我们现在相当于自动配置包变了,所以我们只需要可定install。重新呢,给他装到门有仓库里边,让他更新到最新。好,现在呢,已经给我们完全做好了,我们把这个呢,重新装到了麦文仓库,我们把这个项目兔我们的这个麦文仓库里边,好没问题,然后呢,那接下来来到我们这个测试类里边。来到我们的这个测试类里边,我们测试类里边呢,我们引了这个开发场景starter,我们来刷新一下这个starter呢,重新去me仓库里边来引一遍,引完了以后呢,接下来我们呢,只需要一个简单的开发场景,比如我来准备了一个hello controller hello controller好,我们来放在controller包下走,然后呢,它是一个rest ctrll,接下来它要调用c hellol方法c hellol方法at一个get map,那给谁打招呼呢?我们希望是调用我们抽取的hello service这个组件,好,我们把这个hello service我直接拿来进行自动注入,能不能自动注入能,因为我们写了一个叫hello service auto configuration,诶,这是不是就像那么一回事了,这个auto。
14:29
都configuration呢,给我们项目一启动还会加载,加载呢还会绑定配置文件叫hello properties,所以呢,你想要打招呼有前后缀,那你在这儿呢,可以在你的这个项目里边,诶你引入hello点一个好,我们来给它给一个前缀prex,比如呢我们就叫at硅谷,然后呢,再来给一个后者hello点一个surface,比如呢,我们就叫666,好来随便写了一个,那这样呢,我们的hello service我拿来,我想要给某一个人打招呼,我们就调用hello service打招呼方法就给张三打个招呼,然后最终呢,给你返回一个打招呼的这个字符串。
15:11
我们把这个字符串呢写给浏览器,那这一连串操作我们来看能不能成功来启动我们当前的项目。好,来访问一下我们当前项目的这个请求,Local house8080应该是hello请求,那这个不是hello请求,好,Get map来让它映射一个当前项目的hello请求。呃,我们想要给张三打招呼,而张三打招呼呢,这个前后坠我们已经在这儿配好了,来看我们的这个组件能不能按照这个前后缀来进行工作。
16:00
好,来发送hello,好,我们发现呢,前缀是按照硅谷,后缀呢是666,我们只需要呢,想要修改默认行为,我们只需要修改配置文件就行了,比如我们叫888走起,那这样呢,我们就模拟了一个自定义start,自定义start呢,整个开发逻辑就是这样子的,我来刷新一下,好没问题,那想捋逻辑呢,也非常简单,我们先引入我们的这个自定义start,好,我们这个start呢,帮我们还引入了它的自动配置场景,而自动配置场景呢里边呢,我们来看啊,我们的这个自动配置场景,我们自己starter的自动配置场景在这,我们的这个自动配置场景呢,一启动,他说他用spring说你给我加载hello service自动配置类,所以呢,我们这个hello service的这个自动配置类就加载了,而这个自动配置类一加载呢,它呢又说当容器中没有hello service组件的时候,给我们容器中还放一个组件,而且呢,这些组件的所有属性,因为这个组件它。
17:01
是自动注入helloties的,所有的这个属性呢,也是跟hello proper绑定的,绑定的and硅谷,所以我们只需要修改这个属性就可以了,甚至于呢,如果我们当前自己给容器中注册一个hello service组件,那用的就不是我们这自动配好的,而是别人的,所以我们可以看一下,我们自己再放一个,比如呢,My con enter一个configuation,然后呢,我们这么来写public hello service hello service and being来给容器中自己放一个,放一个什么呢?我要这么来写,我来new一个hello service,我自己放一个这个组件,然后呢,我的这个组件的名字啊,比如我的这个组件里边来看一下啊,我们的这个组件里边呢,还有还要注入hello proper啊,那现在他又住住进来了,我们在这写死了,如果我们这个组件里边呢,有其他的。
18:01
属性相当于我们自己呢,可以给这设置属性,我们呢把我们的这个hello service返回,那自然呢,它就不会调用它的这个hello service了,那我们可以来测试一下这个逻辑,我们看是不是调用了这个hello service。我们来单元测试,我们看是调用了哪个,Hello service是调用了我们的,还是调用了那个,好,我们来全部关掉,重新单元测试。如果这个也能测试成功,那我们所有我们spring boot以前的这些自动配置,我发现呢,都是可用的,好,现在呢,我们发现它在这调用的是我们的hello service方法返回我们的hello service,而不会调用auto configuration的hello service,好,我们看啊,断点没有来到这儿,还是。来直接放行了,所以呢,没有调用到我们这一块的hello service,这就是我们说的,当容器中没有这个组件的时候,我才给你下边所有进行生效,这是我们说的这个逻辑。
19:00
呢,可能会有一处错误,我们来看一下,看这处错误,说hello properties没有在我们这个类中,为什么?是因为我们在这auto compgu我们写的时候,当容器中没有这个组件,我们连hello proper都不搞了,所以呢,如果要把它写完美,那应该是这么来写的。我们的这一块,我们的这个条件装配,我可以给它写到下边,写到这儿,比如说当你容器中没有这个组件的时候,我给你再配置个组件,那无论如何我们在这个配置内绑定都是没问题的,那这种方式的情况下来重新可令尼死掉。那我们的这一块引入呢,就就不会有任何问题了,好,我们重新来到这儿,我们想要再来引入来刷新一下,那我们此时呢,就不会有这个问题了,我们直接项目启动吧,只要项目启动没有给我们说hello properties出现问题,那就没问题。好,他还说hello properties有问题,我们把这个呢,需要清空一下啊。
20:06
我们可令一下。因为我们刚啊,我们刚把这个项目才呃可定,我们来看啊,我们的这个hello特色项目刚可定,然后呢,我们要把我们的这个安装到我们的这个仓库里边,我们先把这个口令掉。然后呢,我们再把它安装到仓库里边,否则呢,我们这个配置就不会生效。好,我们安装到仓库里边没问题了,再来到我们的这个项目里边,来可令来重新运行我们的这个项目。好,我们来重新启动我们的项目,就不会报之前的这个错误了,我们去买仓库呢,引入新版的这个auto包。不会出错误的原因是因为我们的hello service的total configuration,它现在变了,容器中没有这个组件的时候才变成组件,无论何时,那hello properties都是对的。这是我们说的自定义的所有细节。
我来说两句