我们知道在spring容器初始化的时候,底层会基于13个函数去实现bean对象的装载,在这13个函数中spring最终完成了将bean对象存储到容器中的工作。
而这13个函数就阐述了spring容器是怎样把我们配置的xml文件中的bean标签转换成容器中的bean实例的。
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
大致的解释一下每个函数的作用:
1.prepareRefresh();
准备刷新,这一步先不说了,对于我们分析ioc没有任何影响
2.obtainFreshBeanFactory
获取bean factory,对于bean factory这里要解释一下,我们从spring容器中获取对象其实都是在从bean factory中拿对象,它就相当于我们spring的对象池。
在这个过程中,我们看到applicationcontext对象调用了一个方法:loadBeanDefinitions,这个方法点进去我们看到有loadBeanDefinitions这样一个方法,它将配置信息中的bean转换成了beandefinition,由此我们可以得出一个结论:spring容器的IOC流程中,第一步是从xml配置信息读取bean信息,并将它解析成beandefinition,即bean的定义信息,然后将他们放到beanfactory里面,再把beanfactory装载到applicationcontext里面。
3.prepareBeanFactory
准备bean factory,准备工作嘛,定义bean factory,跳过。
4.invokeBeanFactoryPostProcessors
bean factory的后增强,这里很重要,执行了beanfactorypostprocessor。那到底是在干什么呢,其实就是beanfactory的二次初始化。举个例子,我们再配置文件中经常会用到这样的表达式:
${jdbc.url},${jdbc.username}等等,在beanfactory一开始被创建的时候,只是把这些表达式存在了map里面,而这次初始化,就是把实际的值找到再赋给他进行替换。所以这里也是IOC的一个重要步骤:将bean factory中的表达式信息替换成配置文件中的实际的值,即二次初始化
5.registerBeanPostProcessors
注册/记录bean 的后增强器,这里理解这个后增强器即可,后增强器其实就是类似aop的东西,给bean 的生命周期做进一步的增强的,而因为之后要对bean实例化了,所以在实例化之前必须要先把这些增强器先加载到spring里面,简而言之,就是准备工作。
而且我们看到这句英文,
// Register bean processors that intercept bean creation.
所以这里可以理解为正在向spring装载一些interceptor,拦截器
这里是第三步:加载bean的增强器
6.initMessageSource
国际化,忽略
7.initApplicationEventMulticaster
初始化事件的广播器,后面的registerlistener会装载一些监听器嘛,那监听器和广播器肯定要对应,才能构成事件机制啊。这里是第四步:装载bean的广播器
8.onRefresh
模板方法,不管它
9.registerlistener
注册监听器,
10.finishBeanFactoryInitialization
beanfactory的初始化,这里省略详细内容,原理就是反射。。。。。但是这里很重要,是第五步:bean实例化
而同样,如果是通过注解的方式去标注bean,用注解的方式代替xml配置的话,spring也同样会加载到这些注解,装载到spring容器中。如下的方式可以帮我们了解到如何从spring 容器中获取到装载到spring中的bean对象。
public static void main(String[] args) {
//扫描com.jt.pojo包里所有的bean注解
AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext("com.jt.pojo");
TestUser testUser=applicationContext.getBean(TestUser.class);
System.out.println(testUser);
}