【Spring】Bean生命周期源码分析 上篇 实例化前的准备工作

测试Bean

image-20220402195218252

1.容器启动

Spring创建一个容器有多种方式,可以基于配置类,也可以基于xml配置文件,这里使用XML配置的方式创建Spring容器

Debug走起,打下第一个断点

image-20220402195444899

image-20220402195512957

来到 org.springframework.context.support.AbstractApplicationContext.refresh() 方法 refresh是spring容器启动最核心的方法

在这个方法内一共调用了其他12个方法 , 这篇是看Bean的生命周期,所有无关的方法浅浅过一下

image-20220402200031113

第一个方法 prepareRefresh()

// Prepare this context for refreshing.
prepareRefresh();

image-20220402200138646

image-20220402200411029

接下来执行了这一行代码 做了一件非常重要的事情,创建BeanFactory

// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

2. 创建BeanFactory

我们来看下是怎么获取bean工厂的

image-20220402201013476

debug跟进 org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory

image-20220402201203774

image-20220402201225691

return new DefaultListableBeanFactory(getInternalParentBeanFactory());

返回的bean工厂类型为 DefaultListableBeanFactory

如果你下载了源码 可以看到在 BeanFactory 接口注释的全套 bean 生命周期接口 等会我们能在源码中全部看到

Bean 工厂实现应尽可能支持标准的 bean 生命周期接口。全套初始化方法及其标准顺序为:

  1. BeanNameAware’s setBeanName

  2. BeanClassLoaderAware’s setBeanClassLoader

  3. BeanFactoryAware’s setBeanFactory

  4. EnvironmentAware’s setEnvironment

  5. EmbeddedValueResolverAware’s setEmbeddedValueResolver

  6. ResourceLoaderAware’s setResourceLoader (only applicable when running in an application context)

  7. ApplicationEventPublisherAware’s setApplicationEventPublisher (only applicable when running in an application context)

  8. MessageSourceAware’s setMessageSource (only applicable when running in an application context)

  9. ApplicationContextAware’s setApplicationContext (only applicable when running in an application context)

  10. ServletContextAware’s setServletContext (only applicable when running in a web application context)

  11. postProcessBeforeInitialization methods of BeanPostProcessors

  12. InitializingBean’s afterPropertiesSet

  13. a custom init-method definition

  14. postProcessAfterInitialization methods of BeanPostProcessors

在关闭 bean 工厂时,将应用以下生命周期方法:

  1. postProcessBeforeDestruction methods of DestructionAwareBeanPostProcessors
  2. DisposableBean’s destroy
  3. a custom destroy-method definition

回到 org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory

image-20220402202023699

在创建bean工厂后,又调用了三个方法

方法一:设置序列化ID

beanFactory.setSerializationId(getId());

方法二:定制bean工厂 (bean定义是否可以被覆盖,是否运行循环依赖)

customizeBeanFactory(beanFactory);

image-20220402202227244

方法三: 解析bean配置信息,生成BeanDefinitions (下文都将简称为bd)

loadBeanDefinitions(beanFactory);

3.解析生成 BeanDefinitions

debug跟进 来到 org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions()

image-20220402202549429

	XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

创建一个xml解析器,我们使用的xml配置文件启动容器,bean的定义信息都配置在xml中

image-20220402204904250

解析完成后调用 loadBeanDefinitions(beanDefinitionReader)方法,添加到BeanDefinition中

image-20220402203818866

接下来获取所有的配置信息文件,加载

String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}

image-20220402203945173

最终将xml配置文件通过JDK中的JAXP解析为Document对象,然后再注册为bd

注册完bd后,beanFactory中的beanDefinitionMap已经有了bean A的 定义信息 ,将来就可以通过这些定义信息,通过反射实例并初始化一个bean A放到容器中

image-20220402205004034

image-20220402205119334

接下来来到 invokeBeanFactoryPostProcessors(beanFactory)方法 进入执行Bean工厂的后置处理器流程

4.执行Bean工厂的后置处理器方法

image-20220402205718893

Bean工厂的后置处理器方法的执行时机为 初始化bean工厂,并且解析生成bd后,但在bean实例化前

再接着 refresh方法往下走,到第十一个方法 开始进入bean的实例化阶段

finishBeanFactoryInitialization(beanFactory)

5.实例化bean前 applyBeanPostProcessorsBeforeInstantiation 扩展点

来到 org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization

​ 又调用了 beanFactory.preInstantiateSingletons(); 进行初始化所有的单实例Bean

​ org.springframework.beans.factory.support.DefaultListableBeanFactory. preInstantiateSingletons()

image-20220402210730029

首先复制了所有的beanName,放到beanNames中

List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

然后就开始遍历所有的beanName

for (String beanName : beanNames) {
			.....

}

遍历的第一步就是将bd转为RootBeanDefinition统一

RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

接着就是一个三连判断 不能是抽象类,必须是单例,且不是懒加载,继续往下走

if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				

判断是不是工厂bean 测试的bean A是一个普通bean,走else

if (isFactoryBean(beanName))

调用getBean(beanName);方法

​ 又调用 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean

image-20220402211356894

首先获取真正的beanName 去掉工厂bean名称的&前缀以及解析 bean别名

String beanName = transformedBeanName(name);

然后尝试从缓存中拿bean对象

Object sharedInstance = getSingleton(beanName)

来到 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton

首先注意一个方法调用的参数

image-20220402211745945

allowEarlyReference 这个参数的值,默认就是true,用来解决循环依赖的,很重要

接着看这个方法 从一级缓存中拿,一级缓存中都是以及初始化好的单例bean,如果能拿到,直接返回

private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256) 单例缓存池(一级缓存)

Object singletonObject = this.singletonObjects.get(beanName); //singletonObjects  单例缓存池

如果没拿到,并且当前beanName对应的bean正在创建中

private final Set singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16)) 保存正在创建的beanName

if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {

在从二级缓存 earlySingletonObjects 中找

private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16) 二级缓存,实例化,但未属性填充的bean

singletonObject = this.earlySingletonObjects.get(beanName);

没找到继续从三级缓存 singletonObjects 中找

**private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16) 存储生成代理对象的lombda表达式 **

注意这个map的value ObjectFactory<?> 是一个函数式接口,将来用以保存lombda表达式 ,用来解决被AOP代理的bean循环依赖问题

image-20220402212956053

ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);

如果singletonFactory不为空, 将执行 lombda表达式,生成代理类,也就是提前AOP

singletonObject = singletonFactory.getObject();

image-20220402213614956

提前AOP后,又执行了两个有意思的方法

把当前的代理类对象放到二级缓存中,然后删除三级缓存中的entry,这两步非常重要,之后会写一篇循环依赖的博文,在详细说

如果从缓存中都没拿到,直接返回空对象

image-20220402213819171

image-20220402215143093

循环依赖判断,没有循环依赖问题往下走,有循环依赖的对象先创建依赖的对象

image-20220402214942619


当前的bean是单例的,进入if

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;
						}
					});

这里调用了一个 getSingleton 方法 方法有两个参数,一个beanName,还有一个lombda表达式,

执行org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法

image-20220402215320614

首先校验bean的名字不能为空

Assert.notNull(beanName, "Bean name must not be null");

然后再次尝试从缓存中拿对象 上面进去看过了

Object singletonObject = this.singletonObjects.get(beanName);

image-20220402215613991

没拿到进入if判断 执行lombda表达式

image-20220402215637234

执行 createBean(beanName, mbd, args); 方法

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

image-20220402215838411

在bean真正实例化前,还有这么一个方法 能让当前返回代理对象,而不是目标bean对象

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd)

image-20220402220049094

判断容器中是否有InstantiationAwareBeanPostProcessors,如果有,执行InstantiationAwareBeanPostProcessors.applyBeanPostProcessorsBeforeInstantiation方法

image-20220402220213636

实例化之前会调用InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation

Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);

如果有返回对象,改对象将被放到spring容器中,而当前bd封装定义信息所属bean的实例化流程将提前终止,并且执行InstantiationAwareBeanPostProcessor.applyBeanPostProcessorsAfterInitialization 方法

image-20220402220415687

如果返回null,当前bean实例化流程继续往下走

我们没有实现applyBeanPostProcessorsBeforeInstantiation扩展点,继续往下走

image-20220402220559678

来到doCreateBean(beanName, mbdToUse, args)方法

doCreateBean(beanName, mbdToUse, args)

bean实例化前的流程已经完成,开始真正实例化bean了 放到下篇博文

猜你喜欢

转载自blog.csdn.net/JAVAlife2021/article/details/123930142
今日推荐