Spring IoC Bean-生命周期
一、什么是Spring
1、Spring IoC
a.Dependency Injection(DI)–依赖注入
b.Dependency Lookup(DL)–依赖查找
c.Spring容器管理的对象包括什么
2、Spring AOP
二、Spring Bean 生命周期概览
1、概览图
a.Spring Bean的转换过程
下面这张图演示了一个可用的Spring Bean是如何从xml配置文件中演变过来的
ps:配置元信息来源不仅可以在xml中,也可以在properties文件里以及注解元信息。
从上面的图中,我们可以比较清楚的知道Bean的元信息
经过解析得到BeanDefinition
,然后通过InstantiationStrategy策略将Class实例化为相应的Bean实例
,此时该Bean实例字段均为空,然后经过一系列操作将一个可用的Bean实例提供出来供我们使用,在我们使用完之后,容器销毁时,将这些资源进行释放,最终有JVM进行垃圾回收。
b.Spring Bean生命周期概览图
Spring内部IoC容器默认实现为:DefaultListableBeanFactory
Bean的生命周期与方法映射如下图所示:
三、Spring Bean生命周期核心方法
1、registerBeanDefinition-Spring Bean注册
该方法定义于BeanDefinitionRegistry接口下,由DefaultListableBeanFactory提供具体实现,流程比较简单。
其实整个注册流程最核心的一段代码就是:this.beanDefinitionMap.put(beanName, beanDefinition);将相应的BeanDefinition注册到beanDefinitionMap中。key为baneName,value为BeanDefinition
// DefaultListableBeanFactory#registerBeanDefinition
/** Map of bean definition objects, keyed by bean name. */
// 存储beanName(key)与BeanDefinition(value)
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
// 存储beanName,实现容器BeanDefinition的顺序注册
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
/** Whether to allow re-registration of a different definition with the same name. */
// 是否允许相同名称不同BeanDefinition,后者覆盖前者
private boolean allowBeanDefinitionOverriding = true;
/** List of bean definition names, in registration order. */
//---------------------------------------------------------------------
// Implementation of BeanDefinitionRegistry interface
//---------------------------------------------------------------------
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
// <1> 对BeanDefinition的最后一次校验,主要对属性 methodOverrides 进行校验
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
// <2>从缓存中拿BeanDefinition
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
// <2.1>如果缓存中有此BeanDefinition
if (existingDefinition != null) {
// 如果存在但是不允许覆盖,抛出异常
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
// 覆盖 beanDefinition 大于 被覆盖的 beanDefinition 的 ROLE ,打印 info 日志
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
// 覆盖 beanDefinition 与 被覆盖的 beanDefinition 不相同,打印 debug 日志
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
// 其它,打印 trace 日志(很低的一种日志级别,一般不使用)
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
// 进行BeanDefinition覆盖
this.beanDefinitionMap.put(beanName, beanDefinition);
}
// <2.2>正常情况下,注册流程会走下面这个流程:
else {
// 检测Bean创建阶段已经开启,如果开启了就需要对BeanDefinitionMap进行并发控制(这里进行并发控制的原因我理解应该是:如果是Spring容器启动时是单线程的话,那么在注册阶段就不会出现Bean创建阶段的情况,既然出现了不同阶段同时进行的情况,那么一定是处于多线程的情况下,所以需要避免线程不安全的场景,所以需要加锁)
if (hasBeanCreationStarted()) {
// beanDefinitionMap是全局变量,需要进行并发控制,避免并发情况
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
// 将BeanDefinition加入到beanDefinitionMap中
this.beanDefinitionMap.put(beanName, beanDefinition);
// 将beanName加入到beanDefinitionNames中
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
// 从 manualSingletonNames 移除 beanName, manualSingletonNames用于存储registerBeanDefinition外的单例注册bean
removeManualSingletonName(beanName);
}
}
else {
// Still in startup registration phase
// 将BeanDefinition加入到beanDefinitionMap中
this.beanDefinitionMap.put(beanName, beanDefinition);
// 将beanName加入到beanDefinitionNames中
this.beanDefinitionNames.add(beanName);
// 从 manualSingletonNames 移除 beanName, manualSingletonNames用于存储registerBeanDefinition外的单例注册bean
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
// 重新设置 beanName 对应的缓存
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
2、getMergedBeanDefinition-Spring Bean合并
该方法定义于ConfigurableBeanFactory接口下,由AbstractBeanFactory实现(考虑层次性容器)
此方法会返回一个BeanDefinition实例,如果当前Bean有parent指定,那么会返回一个父子合并后的BeanDefinition。
// AbstractBeanFactory#getMergedBeanDefinition
/*用来存储合并后的RootBeanDefinition缓存*/
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
// 考虑层次性容器时会调用此方法(目前学习的过程当中还没有发现哪里有调用此方法)
@Override
public BeanDefinition getMergedBeanDefinition(String name) throws BeansException {
//<1> 根据给定的name获得真正的beanName(有可能给定的name是别名)
String beanName = transformedBeanName(name);
// Efficiently check whether bean definition exists in this factory.
//<2> 当前容器是否包含此BeanDefinition
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
// <2.1> 如果当前容器没有,并且父容器实例是ConfigurableBeanFactory,那么就去到父容器中去递归查找
return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);
}
// Resolve merged bean definition locally.
// <3> 获取当前容器的BeanDefinition
return getMergedLocalBeanDefinition(beanName);
}
// AbstractBeanFactory#getMergedLocalBeanDefinition
// 在spring执行doGetBean()方法时,调用的此方法 主要用于查找当前容器的BeanDefinition(不考虑层次性容器的场景)
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
// <1> 去到mergedBeanDefinitions中查找RootBeanDefinition信息
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
// <2> 如果找到了,并且当前mbd不允许重新合并时,直接返回(stale字段的含义就是决定BeanDefinition是否重新合并)
if (mbd != null && !mbd.stale) {
return mbd;
}
// <3> 重载方法,获取当前容器下父子Bean合并后的BeanDefinition
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
// AbstractBeanFactory#getMergedBeanDefinition
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
throws BeanDefinitionStoreException {
// <1> 重载方法(处理BeanDefinition合并的核心方法)
return getMergedBeanDefinition(beanName, bd, null);
}
// AbstractBeanFactory#getMergedBeanDefinition
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) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
if (mbd == null || mbd.stale) {
previous = mbd;
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 {
String parentBeanName = transformedBeanName(bd.getParentName());
if (!beanName.equals(parentBeanName)) {
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
else {
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without an AbstractBeanFactory parent");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
// Deep copy with overridden values.
mbd = new RootBeanDefinition(pbd);
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;
}
}