关于spring的spi技术

通过spring源码的学习,可以知道spring中拥有很多的拓展,其中有BeanDefinitionRegistryPostProcessor类型类的拓展


在spring加载的时候,会去判断是否拥有BeanDefinitionRegistryPostProcessor类型的类,若是拥有则会执行继承这个类的postProcessBeanDefinitionRegistry()方法,以及postProcessBeanFactory()方法,其中在这两个方法中,拥有参数BeanDefinitionRegistry(BeanDefinition注册器),以及ConfigurableListableBeanFactory(bean工厂),一旦拥有了这两个参数,那咱们就能对spring容器进行操作了。

大致讲一下spring加载的一个流程,在这就不细说了,细说的话,我觉得我可以码一本小说了。(在此细说,仅仅是为了装个小B)

首先spring加载的时候,会将匹配到的.class文件全都转化为BeanDefinition,存放到一个集合中。即:beanDefinitionMap。


然后在beanfactory在getbean()的时候,将beanDefinitionMap拿到,接着生成实例,放到一个容器,即:singletonObjects   可以将它称为:一级缓存。

对于spring来说,他的开闭原则是他的精髓思想,里面内置了很多拓展,因此咱们可以利用这些拓展来对spring的ioc容器进行操作。比如:在还没加入到ioc容器之前,咱们可以自定义一些BeanDefinition,通过BeanDefinition注册器将它放入到BeanDefinition这个map中,这样就能实现ioc的注入了。

另外在注解扫描的时候,有个特有的类,importselect,在扫描到的时候,也会执行importselect方法,我们也可以通过继承importselect来实现BeanDefinition的注入。

既然有了能操作BeanDefinition注册器,以及BeanFactory,那接下来就可以通过读取到配置文件中的内容,将它注入到ioc容器中了。

以下我会用三种方式去实现。

在操作之前,先看一下配置文件的设置


第一种:操作postProcessBeanDefinitionRegistry()


第二种:操作postProcessBeanFactory()


因为需要设置beanName,考虑到首字母小写,因此单独拿出来一个方法去实现


这两种方式,都是通过操作同一个类的,只不过通过操作两个方法去实现,但是功能可以说是一样的,都是通过拿到配置文件的内容,然后将它变为BeanDefinition,然后加入到beanfactory的BeanDefinition集合中。

第三种:


这个方法相对而言有点骚。主要用到@Import方法,通过拿到@import方法中的注解中的参数,拿到配置文件对应的内容,然后拿到类的全限定类名接着返回。

个人而言,这种方式拓展性更强,可以通过jar包的方式,导入,然后在自己项目中设置配置文件导入自己需要指定的的类。

接下来咱们看一下,这个@Import是在那使用的。这边是用了一个注解去导入。


通过这样的方式导入,用来实现三种方式的spi技术。这块功能也完全可以将他变为一个jar包,导入到其他项目中使用。


通过一个简简单单的注解,就能实现了jar包项目中的类导入了。

有人可能会说:@ComponentScan注解不是更方便么?确实,@ComponentScan这个注解很方便,而且也完全是无脑的,但是为啥我还要用这种spi的技术去实现的。说实话:我就是为了装逼。装逼使我快乐,装逼使我开心,我装逼,我骄傲。

有兴趣的可以将这个项目拉下来看一下。

https://github.com/young287/spring_spi_demo 这个是项目地址。

https://github.com/young287/spring5.2.8_yuanma 这个是spring5.2.8源码的地址,里面是我学习了源码以后,在源码里面写的一些注解,有兴趣的小伙伴也可以下载下来看看。

一起努力吧,咱们是目标不是星辰大海,而是怼死面试官。

你可能感兴趣的:(关于spring的spi技术)