Spring源码分析のBean创建流程(上)
文章目录
- 前言
- 一、preInstantiateSingletons
- 1.1、getMergedLocalBeanDefinition
- 1.2、isFactoryBean
- 二、getBean
前言
原生Spring在refresh方法中,会在finishBeanFactoryInitialization
:preInstantiateSingletons
方法中直接创建所有非懒加载的单例Bean
。
一、preInstantiateSingletons
preInstantiateSingletons
方法的主要逻辑:
- 遍历bean名称的集合。
- 合并bean的定义 得到合并后的BeanDefinition。
- 判断bean是否应该在此处被实例化。
- 判断bean是否属于FactoryBean/SmartFactoryBean。
- 进行实例化。
- 实例化完成后,再次判断bean是否实现了SmartInitializingSingleton接口,如果实现了,则回调其中的afterSingletonsInstantiated方法。
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
//存放所有bean的名称
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
//遍历bean名称的集合
for (String beanName : beanNames) {
//1.1 getMergedLocalBeanDefinition 合并bean的定义 得到合并后的BeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//进入该分支的条件
//1、Bean不是抽象的
//2、bean是单例
//3、bean不是懒加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//1.2 isFactoryBean 判断bean是否实现了FactoryBean接口
if (isFactoryBean(beanName)) {
//如果实现了 就获取实现了FactoryBean接口的bean
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
//进行强转 将bean转换为接口FactoryBean的类型
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
//这一块是判断bean实现的是否是SmartFactoryBean SmartFactoryBean 也是继承自 FactoryBean
//只要满足条件,无论是if还是else都会回调SmartFactoryBean 的 isEagerInit 方法的逻辑 这里if分支只是额外加入了安全判断
if (System.getSecuritbeanyManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}
//在创建/获取bean之后 再次进行判断 如果有的bean实现了SmartInitializingSingleton 接口, 同样会去回调其中的afterSingletonsInstantiated方法。
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
}
1.1、getMergedLocalBeanDefinition
getMergedLocalBeanDefinition
方法的作用是,得到合并后的bean定义。这里牵涉到Spring父子容器的概念:
public class Demo1 {
public static void main(String[] args) {
AnnotationConfigApplicationContext contextParent = new AnnotationConfigApplicationContext(AppConfigParent.class);
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(AppConfigParent.class);
context.setParent(contextParent);
context.refresh();
}
}
以上是在配置文件中关于父子容器的定义,假如在context中获取某个bean,而context中没有,就会去它的父容器中找。
而在Spring中,合并父子bean定义,主要的逻辑:
- 如果当前bean没有父类,则直接克隆当前的
BeanDefinition
,并使用它作为最终的合并结果。 - 如果有父类,则递归调用
getMergedLocalBeanDefinition
去进行合并。
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
//去合并后的bean定义缓存中找
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
//如果能找到就直接返回
if (mbd != null && !mbd.stale) {
return mbd;
}
//否则进行合并
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
/**
* 参数一 当前的bean名称 参数二 根据当前bean名称找到的对应的bean定义
*/
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {
//加锁 防止重复合并
synchronized (this.mergedBeanDefinitions) {
RootBeanDefinition mbd = null;
RootBeanDefinition previous = null;
// Check with full lock now in order to enforce the same merged instance.
if (containingBd == null) {
//再次尝试通过beanName 从 mergedBeanDefinitions 中获取RootBeanDefinition
mbd = this.mergedBeanDefinitions.get(beanName);
}
//获取不到 就走合并的逻辑
if (mbd == null || mbd.stale) {
previous = mbd;
//如果当前bean名称找到的对应的bean定义 的 父beanName属性为null
//说明可能两种情况 :1、当前bean定义就是RootBeanDefinition 2、当前bean定义不需要合并
if (bd.getParentName() == null) {
// Use copy of given root bean definition.
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
else {
mbd = new RootBeanDefinition(bd);
}
}
//否则需要合并
else {
// Child bean definition: needs to be merged with parent.
BeanDefinition pbd;
try {
//对当前bean的父bean进行名称转换
String parentBeanName = transformedBeanName(bd.getParentName());
//当前bean名称和父bean名称不相同
if (!beanName.equals(parentBeanName)) {
//递归合并 因为当前bean 的 父bean有可能还有父bean
pbd = getMergedBeanDefinition(parentBeanName);
}
//当前bean名称和父bean名称相同
else {
//获取父 BeanFactory
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
// 从父工厂中获取合并后的父类 BeanDefinition
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
else {
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without a ConfigurableBeanFactory parent");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
// Deep copy with overridden values.
//创建一个新的 RootBeanDefinition,基于父类 BeanDefinition
mbd = new RootBeanDefinition(pbd);
//当前的bd覆盖父类的属性
mbd.overrideFrom(bd);
}
// Set default singleton scope, if not configured before.
//如果没有设置作用域 默认是单例的
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(SCOPE_SINGLETON);
}
// A bean contained in a non-singleton bean cannot be a singleton itself.
// Let's correct this on the fly here, since this might be the result of
// parent-child merging for the outer bean, in which case the original inner bean
// definition will not have inherited the merged outer bean's singleton status.
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}
// Cache the merged bean definition for the time being
// (it might still get re-merged later on in order to pick up metadata changes)
//进行缓存
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
if (previous != null) {
copyRelevantMergedBeanDefinitionCaches(previous, mbd);
}
//返回合并后的定义
return mbd;
}
}
1.2、isFactoryBean
isFactoryBean
主要用于判断当前的bean是否实现了FactoryBean
接口,如果某个类实现了FactoryBean
接口,则会产生两个实例,第一个是实现了FactoryBean
接口的bean的本身,第二个是其中getObject()
方法返回的实例。默认的getBean(),得到的是getObject()
方法返回的实例。如果要获取实现了FactoryBean
接口的bean的本身,则需要getBean()时在名称前加上"&"符号。
@Override
public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
//这里获取到的是实现了`FactoryBean`接口的bean的本身
String beanName = transformedBeanName(name);
//尝试从单例池中获取
Object beanInstance = getSingleton(beanName, false);
//如果获取到了,就判断是否实现了FactoryBean
if (beanInstance != null) {
return (beanInstance instanceof FactoryBean);
}
// 判断是否要从父容器中获取
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
// No bean definition found in this factory -> delegate to parent.
return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
}
//这里也会走bean定义合并
return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
}
/**
* 这里的isFactoryBean属性作为一个缓存的效果,后续直接取该类bean定义的该属性的值即可。
*
*/
protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
//尝试从合并后的bean定义中 获取isFactoryBean属性
Boolean result = mbd.isFactoryBean;
//获取不到
if (result == null) {
//判断当前bean是否实现了FactoryBean接口
Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);
result = (beanType != null && FactoryBean.class.isAssignableFrom(beanType));
//并且将isFactoryBean属性设置值。
mbd.isFactoryBean = result;
}
return result;
}
二、getBean
getBean
是Spring创建所有非懒加载单例bean的方法,总体的逻辑,如果容器中已经有了目标bean,就直接返回,否则就去创建。
该方法有以下的情况:
- 单例池中能获取到,走实例化 bean 的逻辑。
- 单例池中没有,Bean 父工厂不为空并且在 Bean 定义中不存在该 BeanName,委托给父工厂。父工厂会尝试获取该 Bean,如果父工厂也没有,则继续查找。
- 单例池中没有,Bean 父工厂为空并且在 Bean 定义中存在该 BeanName,则进行 Bean 定义合并。合并时,父 Bean 定义会被合并到当前 Bean 定义中,最终生成 Bean 实例。
- 根据 Bean 的作用域执行不同操作:
- 单例 Bean:创建后加入单例缓存池,后续请求直接返回缓存中的实例。
- 原型 Bean:每次请求创建新的实例,不缓存。
- 其他作用域:根据配置的作用域(如 request、session 等)执行对应的实例化和管理逻辑。
- 循环依赖的处理:Spring 会通过提前暴露实例来解决 单例 Bean 的循环依赖问题,原型 Bean 则无法解决循环依赖。
- 初始化和销毁:Spring 会在容器启动时初始化单例 Bean,并处理 Bean 的初始化和销毁方法。
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
//对bean的名称进行转换 这里会去除beanName中的&
String beanName = transformedBeanName(name);
Object beanInstance;
// Eagerly check singleton cache for manually registered singletons.
//尝试从单例池中获取bean
Object sharedInstance = getSingleton(beanName);
//单例池中能获取到
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//实例化bean
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
//单例池中没有 说明是第一次获取
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
//判断是否存在循环依赖的问题
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
//得到bean工厂
BeanFactory parentBeanFactory = getParentBeanFactory();
//bean工厂不为空 并且在bean定义中不存在该beanName
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
//如果传入的name中,有&字符串,则在此处重新加上&字符串
String nameToLookup = originalBeanName(name);
// 如果父工厂是 AbstractBeanFactory 类型
if (parentBeanFactory instanceof AbstractBeanFactory) {
// 委托给父工厂执行 doGetBean 方法,查找并返回 Bean 实例
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
// 如果传入了构造参数 args
else if (args != null) {
// 委托给父工厂并传递构造参数来获取 Bean 实例
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
// 如果指定了 requiredType 类型
else if (requiredType != null) {
// 委托给父工厂的标准 getBean 方法
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
// 委托给父工厂的标准 getBean 方法,返回该 Bean
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
//进行bean定义合并
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
//如果bean定义是抽象的,则抛出异常
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
//找到该bean定义的DependsOn属性。
//@DependsOn注解,用于标记在创建该bean时,应该先创建该bean依赖的某个bean
String[] dependsOn = mbd.getDependsOn();
//如果存在依赖的bean
if (dependsOn != null) {
for (String dep : dependsOn) {
//这里是对于循环依赖的判断 即当前bean所依赖的bean,又依赖了当前bean
//这种情况等价于 构造方法的循环依赖 无解 所以直接抛出异常
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
//注册bean的依赖关系
registerDependentBean(dep, beanName);
try {
//先去创建当前bean所依赖的bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 下面这一段的逻辑 根据bean不同的作用域 执行不同的操作 单例bean就直接创建 并加入单例池
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//原型bean会创建 不会被缓存
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
//其他的作用域,走自己的初始化逻辑
else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
}
catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
finally {
beanCreation.end();
}
}
return adaptBeanInstance(name, beanInstance, requiredType);
}
其中bean的依赖关系,是存放在DefaultSingletonBeanRegistry
的成员变量中:
dependentBeanMap: 当前bean被哪些bean依赖;dependenciesForBeanMap:当前bean依赖了哪些bean
然后会调用createBean
方法完成bean的创建。