1. 概述
在之前的文章中有提到过,SpringIOC
容器管理了我们定义的各种Bean
对象及其相互的关系,Bean
对象在Spring
实现中是以BeanDefinition
来描述的;
BeanDefinition
也叫spring bean
的建模对象,也就是把可以表示bean
的模型对象;
在学习JVM
虚拟机的时候,了解到普通类的实例化过程是先将java
文件编译成class
文件,继而java虚拟机启动会把这些class
文件load
到内存,当遇到new
关键字的时候会根据类的模板信息实例化这个对象也就是在堆上面分配内存
但是对于Spring
来说实例化一个bean
的过程更为复杂,因为它涉及到bean
的一些配置,如懒加载的,作用域等信息,Class
无法完成对带有这些额外信息的bean
的抽象,故而需要一个BeanDefinition
类来抽象这些信息,以便于spring
能够完美的实例化一个bean
2. spring
的bean
实例化过程
记录一下子路老师的spring源码系列(三)——beanDefinition(1)
假设在你的项目或者磁盘上有X和Y两个类,X是被加了spring
注解的,Y没有加spring
的注解;也就是正常情况下当spring
容器启动之后通过getBean(X)
能正常返回X
的bean
,但是如果getBean(Y)
则会出异常,因为Y
不能被spring
容器扫描到不能被正常实例化;
① 当spring容器启动的时候会去调用ConfigurationClassPostProcessor
这个bean
工厂的后置处理器完成扫描,也就是把类的信息读取到,比如类的类型(class
),比如类的名字,类的构造方法,scope
,lazy
,dependsOn
等等信息
② 当spring
读取到类的信息之后会实例化一个BeanDefinition
的对象,继而调用这个对象的各种set
方法存储信息;每扫描到一个符合规则的类,spring
都会实例化一个BeanDefinition
对象,然后把根据类的类名生成一个bean
的名字(比如一个类IndexService
,spring
会根据类名IndexService
生成一个bean
的名字indexService
,spring
内部有一套默认的名字生成规则,但是程序员可以提供自己的名字生成器覆盖spring
内置的)
③ 继而spring
会把这个beanDefinition
对象和生成的beanName
放到一个map
当中,key=beanName,value=beanDefinition
对象,这个map
专门用来存beanDefinition
走到这一步,就可以使用得到的beanDefinition
生成想要的对象了,Spring
也为我们提供了另一条路,也就是BeanFactoryPostProcessor
,后置处理器,它能够在应用程序上下文的标准初始化之后修改它的内部bean
工厂,是spring
提供的一个扩展点
④当spring
把类所对应的beanDefintion
对象存到map
之后,spring
会调用程序员提供的bean
工厂后置处理器,在应用程序上下文的标准初始化之后修改它的内部bean
工厂
3. BeanFactoryPostProcessor
后置处理器
BeanFactoryPostProcessor
可以在应用程序上下文的标准初始化之后修改它的内部bean
工厂,是spring
提供的一个扩展点(spring
提供很多扩展点,学习spring
源码的一个非常重要的原因就是要学会这些扩展点,以便对spring做二次开发或者写出优雅的插件),可以让程序员干预bean
工厂的初始化过程,比如给beanFactory
中新增bean
,修改bean
@Component
public class TestBeanFactoryPostPorcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
//转换为子类,因为父类没有添加beanDefintion对象的api
DefaultListableBeanFactory defaultbf =
(DefaultListableBeanFactory) beanFactory;
//new一个Y的beanDefinition对象,方便测试动态添加
GenericBeanDefinition y= new GenericBeanDefinition();
y.setBeanClass(Y.class);
//添加一个beanDefinition对象,原本这个Y没有被spring扫描到
defaultbf.registerBeanDefinition("y", y);
//得到一个已经被扫描出来的beanDefintion对象x
//因为X本来就被扫描出来了,所以是直接从map中获取
BeanDefinition x = defaultbf.getBeanDefinition("x");
//修改这个X的beanDefintion对象的class为Z
//原本这个x代表的class为X.class;现在为Z.class
x.setBeanClassName("com.luban.beanDefinition.Z");
}
}