1

上篇《Spring类扫描器记录》中, 记录了Spring扫描Class, 封装成一个个BeanDefinition的过程, ApplicationContext后续将根据这些Bean定义来创建Bean实例, BeanDefinition和Bean实例保存在的位置如下:

BeanDefinition保存到的实例变量(DefaultListableBeanFactory):

/** List of bean definition names, in registration order */
List<String> beanDefinitionNames

/** Map from bean name to merged RootBeanDefinition */
Map<String, RootBeanDefinition> mergedBeanDefinitions

Bean实例保存到的成员变量(DefaultListableBeanFactory):

/** 保存单例对象: bean名 --> bean实例 */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);

一个[BeanDefinition]到一个[Bean实例]是通过BeanFactory#getBean方法完成的:

BeanFactory#getBean方法执行过程:

Tags:(BeanFactory具体对应的子类是DefaultListableBeanFactory)

  1. 从单例缓存singletonObjects查找, 有则直接返回

没有则

  1. 创建实例
  2. 执行bean后置处理器,调用Bean初始化方法
    依赖注入是后置处理完成的,也是调用BeanFactory#getBean获取依赖对象
  3. 保存实例到singletonObjects中

参考百度脑图: [调用beanFactory.getBean获取/创建实例]节点

问题记录

1. 实例化Bean的位置

在上下文刷新时AbstractApplicationContext#refresh

// 执行完全部的BeanFactory后置处理
// ConfigurationClassPostProcessor会加载工程下的class到BeanDefinition
// 注册Bean后置处理器

// 根据BeanDefinition实例化所有单例Bean.
finishBeanFactoryInitialization(beanFactory);

2. 对象循环引用问题

getBean方法通过Bean后置处理器AutowiredAnnotationBeanPostProcessor注入依赖, 该后置处理器又将调用getBean获取依赖Bean, 例如有如下代码:

@Service
public class ServiceA {
    @Autowired
    ServiceB serviceB;
}

@Service
public class ServiceB {
    @Autowired
    ServiceA serviceA;
}

BeanFactory会将创建中的bean名保存到singletonsCurrentlyInCreation, 创建中的bean实例保存到singletonFactories。

getBean("serviceA")的过程:

  1. 创建ServiceA实例
  2. 创建ServiceB实例
  3. 实例ServiceA注入到ServiceB (实例ServiceA仍在初始化中)
  4. ServiceB完成创建
  5. 实例ServiceB注入到ServiceA
  6. ServiceA完成创建

被依赖的Bean会先完成初始化
参考图片链接: Spring循环引用逻辑结构图

3. 单例Bean创建后注册到哪了?

DefaultSingletonBeanRegistry对象的singletonObjects字段, 这里注册的都是依赖已经注入, 且执行完Bean后置处理器的实例

/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);

4. 对象循环依赖异常

BeanCreationException: Circular depends-on relationship between
循环依赖会导致该异常, 如使用@DependsOn注解配置了依赖:

@Service
@DependsOn("permission")
public class Role {
    @Autowired
    private Permission permission;
}


@Service
@DependsOn("role")
public class Permission {
    @Autowired
    private Role role;
}

Permission,Role互相依赖, 谁无法被创建, BeanFactory将抛出异常
BeanCreationException:
Circular depends-on relationship between 'role' and 'permission'


YYGP
25 声望11 粉丝

写BUG