继上篇详解Spring中Bean的加载(一),现在继续讲解bean的创建,先看看createBean()方法源码(该方法在AbstractAutowireCapableBeanFactory类中):
从createBean()方法源码可以看出主要做了以下操作:
-
根据设置的class属性或根据className来解析Class;
-
对覆盖进行标记并验证,在Spring配置中是存在lookup-mothod和replace-method的,这两个配置的加载其实就是将配置统一存放在BeanDefinition中的methodOverrides属性里,这个方法的操作也就是针对于这两个配置的;
-
应用初始化前的后处理器,最后创建bean。
在createBean()方法里执行完resolveBeforeInstantiation方法后,如果创建了代理且不为空的话就直接返回,否则需要进行常规bean的创建,这个创建过程是在doCreateBean中完成的,跟进源码:
上面源码完成的操作可以概括为以下几点:
-
开始是单例的话要先清除缓存;
-
实例化bean,将BeanDefinition转换为BeanWrapper;
-
使用MergedBeanDefinitionPostProcessor,Autowired注解就是通过此方法实现类型的预解析;
-
解决循环依赖问题;
-
填充属性,将属性填充到bean实例中;
-
注册DisposableBean;
-
创建完成并返回
接下来创建bean实例,看createBeanInstance()方法:
可以看出如果在RootBeanDefinition中存在factoryMethodName属性,或者说配置文件中配置了factory-method,那么Spring会尝试使用instantiateUsingFactoryMethod(beanName, mbd, args)方法根据RootBeanDefinition中的配置生成bean实例。
再解析构造方法并进行实例化,Spring会根据参数及类型判断使用哪个构造方法再进行实例化。判断调用哪个构造方法的过程会采用缓存机制,如果已经解析过则不需要重复解析而是从RootBeanDefinition中的属性resolvedConstructorOrFactoryMethod缓存的值去取,不然则需要再次解析。
创建bean后接下来就进行属性注入,属性注入的操作在populateBean()方法中,跟进源码:
在populateBean方法的中的主要处理流程:
-
InstantiationAwareBeanPostProcessor处理器的postProcessAfterInstantiation方法控制程序是否继续填充属性;
-
根据注入类型提取依赖的bean,并存入PropertyValues中;
-
应用InstantiationAwareBeanPostProcessor处理器的postProcessPropertyValues方法对属性在填充前再次处理,主要还是验证属性;
-
将所有PropertyValues中的属性填充到BeanWrapper中。
最后初始化bean
学过Spring的都知道bean配置时有一个init-method属性,这个属性的作用是在bean实例化前调用init-method指定的方法进行需要的实例化操作,现在就进入这个方法了;Spring中程序已经执行过bean的实例化,并且进行了属性的填充,而就在这时将会调用用户设定的初始化方法。
invokeInitMethods调用初始化方法
最后加载完Bean并执行完初始化操作后,一个bean的加载基本就结束了。