首页 > 从源码级别讲解spring bean初始化的整个流程
头像
索引为零的牛油果
编辑于 2021-01-12 16:44
+ 关注

从源码级别讲解spring bean初始化的整个流程

首先需要准备好beanDefinition,准备的整个过程大致分为三步,定位(资源文件)、加载(beanDefinition)、注册(beanDefinition)。先由DefaultResourceLoader定位读取资源文件,将资源文件转为document对象。BeanDefinitionDocumentReader负责读取document对象,将document对象解析加载成beanDefinition,整个解析加载过程在registerBeanDefinitions中进行。解析过程中,首先获得document对象根元素的子节点,对这些子节点依次解析,对<import />、<alias />、<bean />、<beans />等标签的解析等。例如对<bean/>标签的解析,首先会先获取bean标签中的id、name、alias(在此后中,id即作为beanName,如果配置文件中没有配置id,则默认取alias中的首个元素作为beanName),然后继续解析该bean标签中的属性,例如scope、abstract、lazy-init、autowire、depends-on、autowire-candidate、primary、init-method、destroy-method、factory-method、factory-bean,然后解析bean标签里面的description、meta、lookup-method、replaced-method、constructor-arg、property以及qualifier标签。在解析property子标签会判断是否具有子元素list、map、set等集合,最终这些信息都存到beanDefinition的持有者BeanDefinitionHolder中,然后调用BeanDefinitionReaderUtils的registerBeanDefinition对当前解析好的beanDefinition进行注册,根据key:beanName value:beanDefinition注册到beanDefinitionMap中,在注册前会判断是否允许覆盖beanDefinition,因为可能存在相同beanName的beanDefinition已经在容器中了,如果允许覆盖,便可将该beanDefinition覆盖过去。如果是新的beanDefinition,则全新注册,会注册到beanDefinitionMap、beanDefinitionNames、manualSingletonNames这三个集合中。同时会根据key:alias value:beanName注册到aliasMap中。

到这里,spring就完成了对beanDefinition的定位加载注册。接下来就可以根据这些beanDefinition来创建bean。

创建bean的过程很复杂,这里只描述singleton bean的创建过程。

在preInstantiateSingletons中,首先会遍历beanDefinitionNames(这个集合是在注册beanDefinition的时候注册的),获取beanNames集合,然后遍历beanName。首先会根据beanName得到对应的beanDefinition,根据beanDefinition判断是否非抽象且单例且非懒加载,判断是否为FactoryBean,如果不是,直接调用getBean实例化普通bean,若是,则继续判断是否需要预实例化(isEagerInit),需要才调用getBean。

getBean是一个空壳方法,里面只做了一件事,只调用doGetBean。

在doGetBean中,首先会将beanName校验转为spring的规范名称,然后拿着这个beanName去getSingleton得到一个Object,此时这个Object一定为null。因为在getSingleton中,会先去singletonObjects中查,如果为null再去earlySingletonObjects查找,再为null再去singletonFactories中查。显然这个阶段刚开始初始化,这些结合中必然没有对应于beanName的数据。然后还不着急开始创建,在当前容器中查找不到对应于这个beanName的bean,会继续向上级父容器中查找,也即去父容器中调用getBean,必然是返回null的。这回检索工作都做完了,哪里都找不到对应于这个beanName的bean,那就开始创建吧~~~

首先会判断要创建的bean是否为singleton,显然全都是singleton的,因为在上一层(preInstantiateSingletons方法)中已经做了只有singleton的才能调用getBean。

接下来会再次调用getSingleton方法,这个getSingleton方法和上面的是重载方法,这个重载方法负责了创建bean并注册的职责。进入getSingleton方***再次检查singletonObjects中是否有该bean,有则返回,否者先将该bean标记为正在创建中(singletonsCurrentlyInCreation.add(beanName)),然后调用singletonFactory.getObject()方法,这是个回调方***触发getSingleton方法中的第二个参数,进入createBean方法中,是这个createBean返回的singletonFactory。

进入createBean方法,总共会调用七八次后置处理器。该方法中有个doCreateBean方法,这是真正创建bean的方法。

在doCreateBean方法中先创建bean实例包装到BeanWrapper中(createBeanInstance方法),先判断是否有工厂方法,如果有,则使用工厂方法(factory-method)初始化策略,否者按照默认的方法创建bean,选择是用构造器自动装配还是使用默认构造器进行初始化,初始化也是有两种策略,一种是jdk,一种则是cglib。初始化完成后会将该object包装到BeanWrapper中返回出去。然后继续判断是否支持循环依赖,如果支持,就先把singletonFactory注册到singletonFactories中(这里是之后为了解决循环依赖)。到这里,就初始化好了object,接下来就是要开始对初始化完成的objec进行属性填充(populateBean方法)。在populateBean中,则是根据各种策略对object注入属性值,首先先根据名称注入(autowireByName方法(里面调用getBean))(在xml中配置 autowire="byName"),然后再根据类型注入(autowireByType方法(里面调用getBean))(在xml中配置 autowire="byType"),然后才是遍历各种后置处理器,对被@Autowired、@Value、@Resource等修饰的属性进行注入,例如@AutoWired对应的后置处理器是AutowiredAnnotationBeanPostProcessor(同样里面也会调用getBean方法),到这里,所有的需要处理的属性都注入了,但是还差一步,就是这些完成注入的值还没有真正的应用到目标object上,这个动作的处理在applyPropertyValues方法中进行。到了这里,已经完成了对object的初始化以及属性赋值,接下来是对目标object做一些拓展,处理实现Aware接口的回调、对aop的处理、对init-method以及InitializingBean的处理等(initializeBean方法)。在initializeBean方法中,有个invokeAwareMethods方法,则是用来处理对Aware接口的回调,如果实现了BeanNameAware接口,则将beanName设置到目标object本身;如果实现了BeanClassLoaderAware接口,则将当前的类加载器设置到目标object本身;如果实现了BeanFactoryAware接口(实现了这个接口也可以实现属性注入,但是这样就把注入对象的主动权放在类本身,但是这样就和spring强耦合,lookup-method则不会),则将beanFactory设置到目标object本身。接下来是执行applyBeanPostProcessorsBeforeInitialization方法,这个方法执行一些后置处理器,例如会执行注解版的生命周期初始化回调方法(@PostConstruct)等。然后是执行invokeInitMethods方法,这个方法就是处理对InitializingBean的回调和bean标签的属性配置init-method的回调方法。然后继续执行applyBeanPostProcessorsAfterInitialization方法,也是为该object应用上各种后置处理器,例如对aop的代理。如果配置文件中配置<aop:>,则会调用AbstractAdvisorAutoProxyCreator这个处理器的postProcessAfterInitialization方法,在该方法决策使用jdk动态代理或者cglib动态代理,最终替换原来的object。到这里,已经完成了对object的初始化、属性填充、拓展,基本上一个bean就要生产完成,在这之前,继续判断这个bean是否需要销毁方法(registerDisposableBeanIfNecessary方法),registerDisposableBeanIfNecessary方法中会将需要销毁的singleton bean的根据key:beanName value:bean存到disposableBeans中。

到这里,object的一切操作都完成,接下来就是注册到spring的容器中。回到singletonFactory.getObject(),继续执行到addSingleton方法中,会注册singletonObjects和registeredSingletons,移除singletonFactories和earlySingletonObjects(因为bean已经完全注册,对应的早期暴露出来的对象和相应用来生产该object的工厂就不需要了),终于到这里,一个singleton bean就现世了!

待所有的bean都处理完成后,在doGetBean最后会遍历beanNames,对singleton且实现SmartInitializingSingleton接口的bean进行方法回调,用来解决一些因为bean初始化太早而出现的错误问题。

Over!!!

全部评论

(1) 回帖
加载中...
话题 回帖

相关热帖

热门推荐