spring中存储的Bean有些是spring框架自己提供并且自己使用的,他们由spring自行创建并且由框架内部按需调用;有些是用户创建好并交付spring进行管理的。我们将后一种bean称之为用户自定义Bean,我们重点解释这种Bean的创建流程。
我们首先介绍在没有循环依赖,并且没有AOP代理的情况下,spring中Bean的创建流程。这是spring中用户自定义Bean的最普通的创建流程。
创建Bean的前提条件是否具备?
spring中用户自定义Bean可以创建需要几个前提,首先是该Bean对应的BeanDefinition已经创建完成,并且在BeanFactoryPostProcessor接口的目标方法(如果有的话),已经调用过,同时各种自定义的BeanPostProcessor实现类已经完成创建。这时候,万事俱备,就开始了Bean的创建。
在封装复杂的源码中找到创建Bean的关键方法
不论是以注解的方式启动spring环境还是以XML方式启动,在对应的ApplicationContext上下文对象的构造方法中都要调用一个很重要的方法refresh( )。Bean的实例化发生在refresh内部,finishBeanFactoryInitialization(beanFactory);这个方法的调用中。
在finishBeanFactoryInitialization(beanFactory)方法内部,经过一系列调用,创建流程会转入到如下方法中:
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
......//此处非普通Bean创建流程,省去
}
else {
//外部有for循环,用来循环创建所有Bean,将每个beanName排除factoryBean后尝试get,如果没有get到,就进入创建逻辑。此处返回值一定是存到单例池缓存中的
getBean(beanName);
}
}
}
......
可以看到,所有需要创建的Bean都保存到一个叫做beanNames的List中,对这个list中的beanName进行遍历, 拿到每一个beanName对应的BeanDefinition。如果这个BeanDefinition同时满足非抽象类,不存在懒加载,并且是单例的,这里就要对其进行创建。创建流程经过一系列判断,最终走到了getBean(beanName)这个环节;
为什么是getBean()?
此处大家想一想,既然Bean还没有创建,调用的方法为啥不是InitializationBean呢?此处在后边讲到依赖注入的时候还会细讲:是因为在某些类的创建过程中因为存在循环依赖,或者DI的需要,进行了提前的创建,故而这里是可以get到实例的。而大多数Bean没有提前创建的,就需要在此处进行创建。
既然,有些类已经有实例,而有些类没有。可以想象到getBean内部的流程应该会是这样的:
Object bean = getInstance(beanName);
if(bean != null){
return bean;
}
return createNewInstance(beanName);
spring 在实际当中的操作比这个要复杂许多,流程如下,在关键的地方我都进行了注释
可以看到,return 返回的 Bean来自sharedInstance;虽然这个sharedInstance通过getObjectForBeanInstance()方法进行了处理。但是最终的return 的bean的来源,是sharedInstance;
sharedInstance又从何而来呢?很显然来自于getSingleton( )方法的返回值,getSingleton( )内部返回了哪个值呢:就是29行createBean(beanName,mbd,args)的返回值。
再进入这个方法内部,就来到了处理Bean创建流程的具体方法doCreateBean(beanName,mbdToUse,args);
下面给出,一个不包含循环依赖,不进行AOP代理的普通Bean的完整调用链:doCreateBean方法内部是创建一个Bean的具体流程,下一篇将详细介绍。
调用链详解: