通常我们说,spring容器帮我们管理bean,但是什么是bean?
举个简单的例子,如果我们自己提供一个X.class类,那此时的X.class我们称之为class对象,在经过spring的一些列生命周期的处理之后,就会变成可以放到spring容器中的bean对象,我们称此时的对象是bean对象,所以,总结来说,就是经过一系列生命周期方法处理之后的class对象,就是bean对象;
只有经过一系列后置处理器方法的处理,才是一个合格的bean对象
bean对象最终是存储spring容器中,我们简单的、狭义上的spring容器,在spring源码底层就是一个map集合,这个map集合存储的key是当前bean的name,如果不指定,默认的class类型首字母小写,value是bean对象
问题思考
spring为什么不在扫码到class文件之后,立即执行生命周期方法进行初始化、实例化?而是要先放到beanDefinitionMap集合中?
因为spring所提供的容器管理功能中,某些class类并不一定是立马需要初始化的,比如:原型bean,就是在使用的时候,再去初始化
那我们想下,如果是原型bean,并且假设我们没有beanDefinition这一层,那问题就大了,对于原型的bean,我每初始化一次,就需要去扫描一次,这样就很浪费时间了,此时,beanDefinition的作用,就显而易见了,提一嘴,我之前在博客中,多次说到过,我认为spring容器在启动的过程中,对bean进行初始化实例化的时候,大致是分为了两步,第一是讲class文件转换为beanDefinition对象,第二步是根据beanDefinition对象,按照配置的要求,去进行初始化、实例化
有了beanDefinition之后,beanDefinitionMap相当于一个中转站,所有要初始化的bean,都是以beanDefinitionMap中的beanDefinition的属性信息为准
1.spring在将class文件转换为beanDefinition的时候,是没有额外的要求的,不管这个bean是单例的,还是原型的,还是懒加载的,都会扫描出来,统一放到beanDefinitionMap集合中
2.在第二步去初始化bean的时候,才会判断当前bean是否是原型的、是否是懒加载的、是否是有依赖关系的,等
所以,我们也可以认为beanDefinition是一个中转站,这个中转站中,存放了所有的class对应的信息,如果是初始化,就根据beanDefinition的属性信息去初始化,所以,spring也提供了一些列的扩展点让我们去修改beanDefinition、增加、删除beanDefinition
所以,简单来说,我们自己写得一个class文件,在放到spring容器中,是这样的一个步骤:
A.class --> beanDefinition --> bean
所以,中间加了一层beanDefinition之后,那很有可能就会出现,我们提供的是X.class,但是在将class存入到beanDefinition之后,将对应的beanDefinition属性的beanClass设置为了Y.class,那这时候初始化的就是Y对象,而不是X对象
这只是举个例子,想要说明的是:我们提供了一个X.class,正常情况下,初始化的就是x这个bean,但是在特殊情况下,我们可以将X的beanDefinition的beanClass修改为Y.class,这样就偷天换日了,实际初始化的是Y对象;这个过程就依赖于spring所提供的N多个扩展点
在将class放入到beanDefinitionMap之后,可以通过扩展点去修改beanDefinition的属性信息
所以,我们提供的X类,最后并不一定初始化的就是X这个bean,许多底层框架,也是通过beanDefinition的扩展点去完成自己的业务逻辑的
如果我们想对spring对class初始化的过程中,进行干预怎么办?
spring提供了一些列的扩展点,让我们根据自己的业务需求,去处理class文件从class变成bean对象过程中的关键点,具体,可以看前面笔记中,记录的关于spring扩展的相关的笔记,我觉得,这也是spring强大的地方,不仅仅帮我们去管理bean,也提供了相应的扩展点,让我们根据自己的需求去扩展spring,比如:beanFactoryPostProcessor可以让我们去干预beanDefinitionMap中的beanDefinition对象;spring的后置处理器,可以让我们根据自己的需求,去干预各个后置处理器方法执行的逻辑