代码入口:DefaultListableBeanFactory.preInstantiateSingletons()
Spring 在合并 BeanDefinition 之后,调用 AbstractBeanFactory.getBean()
获取 Bean
AbstractBeanFactory.getBean()
有许多重载方法,其最终调用的是
protected <T> T doGetBean(
final String name,
@Nullable final Class<T> requiredType,
@Nullable final Object[] args,
boolean typeCheckOnly)
其目的是为了获取 Bean,先从缓存中获取,如果不存在就创建 Bean。
主体逻辑
- 处理别名、处理 FactoryBean 的前缀,获取最终实际的 Bean name
- 尝试从单例池
singletonObjects
中获取 Bean - 如果获取到 Bean 直接返回,否则继续执行
- 如果当前 BeanFactory 中不包含此 Bean,则调用父 BeanFactory 执行 getBean 方法
- 获取合并后的 BeanDefinition
- 判断如果是抽象 BeanDefinition,无法实例化,报错
- 判断是否有
@dependsOn
注解,如果有:- 有
@dependsOn
注解指定依赖,判断是否循环依赖- 是循环依赖,抛出异常
- 不是循环依赖
- Bean 依赖信息缓存到
DefaultSingletonBeanRegistry.dependentBeanMap
- 执行
getBean()
实例化被依赖的 Bean
- Bean 依赖信息缓存到
- 有
- 判断 Bean 的 Scope 属性
- 单例(Singleton):从单例池中获取 Bean,如果没有,创建 Bean
- 多例(Prototype):创建 Bean
- 其他(Request、Session 等):判断各自的缓存池,获取 Bean,如果没有,则创建 Bean
- 创建 Bean
get FactoryBean
getBean(FACTORY_BEAN_PREFIX + beanName)
getBean 方法可以获取普通 Bean 和 FactoryBean。
如果传入参数 beanName 以“&”(FACTORY_BEAN_PREFIX
) 开头(由于 FactoryBean 有多级继承关系,所以“&”可以有多个,例如“&&&demoService” ),表示希望获取 FactoryBean,则 Spring 将前缀的“&”去除,在单例池中获取到 FactoryBean 后直接返回;
如果传入参数 beanName 不以“&”开头,但在单例池中获取的 bean 是 FactoryBean,表示希望获取 FactoryBean 生产的 bean,则到缓存 factoryBeanObjectCache
中获取,如果没有,则调用 FactoryBean.getObject()
获取 bean,放入缓存中后返回。