通过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源码的地址,里面是我学习了源码以后,在源码里面写的一些注解,有兴趣的小伙伴也可以下载下来看看。
一起努力吧,咱们是目标不是星辰大海,而是怼死面试官。