栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring-Bean的生命周期

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring-Bean的生命周期

前言:

        关于Spring中Bean的声明周期的管理,网上有很多写的非常好的资源。但是由于我记性不好,看一次忘一次,索性自己在这里记一版简单版,用于面试的解释。

        ps:该记录仅供参考,对错不负责任,如果大佬们发现有记录不对的地方,请及时私信或评论。

目录

前言:

Spring-Bean生命周期的两大过程。

Spring 加载bean对象的入口

重要方法解释

Spring-Bean声明周期的两大过程

        从资源或者注解标注的类 到 BeanDefination对象;从BeanDefination对象到Bean对象

Spring 加载bean对象的入口

        首先说明一下,接口BeanFactory是整个Spring bean容器的入库。在该接口上的注释也说明了这一点:The root interface for accessing a Spring bean container。

        但是BeanFactory只是一个接口,其实现是落在了他的实现类上,所以当Spring加载Bean对象时,会通过各种复杂的继承关系,最终将入口定位在类AbstractApplicationContext的refresh()方法上。(注:此refre()方法十分重要)

        先附上源码:

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 做准备,此方法可不深究
			prepareRefresh();

			// 重要方法一
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// 补充beanFactory的设置
			prepareBeanFactory(beanFactory);

			try {
				// 此方法可忽略
				postProcessBeanFactory(beanFactory);

				// 重要方法二
				invokeBeanFactoryPostProcessors(beanFactory);

				// 重要方法三:Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				... 忽略

				// 重要方法四:实例化所有非延迟加载的bean
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

重要方法一:obtainFreshBeanFactory

该方法的作用:解析xml配置文件并注册到BeanFactory中

  1. 创建beanFactory(这里创建的是DefaultListableBeanFactory);
  2. 通过调用loadBeanDefinitions(beanFactory)方法,扫描xml文件配置的bean信息转为beanDefinition对象,并通过BeanDefinitionRegistry注册到1.1的beanFactory中 
    1. 得到所有spring相关的xml,将其转为document对象
    2. 解析document对象,并处理命名空间
    3. 注册beanDefinition对象到beanFactory中,并保留原始属性值(即:如果xml文件中标签下的占位符,此时不做替换处理)。
  3. 该方法详细流程,可直接百度obtainFreshBeanFactory 方法 即可。

重要方法二:invokeBeanFactoryPostProcessors

该方法的作用:调用在上下文中注册为 bean 的BeanFactory增强器,即DefaultListableBeanFactory的增强器)

  1. 在方法PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(*,*)
    替换beanDefinition对象的占位符为实际值,获取最终的BeanDefinition对象
  2. ,context:component-scan 标签的解析由ComponentScanBeanDefinitionParser进行解析,获取base-package值并解析成数组。然后创建ClassPathBeanDefinitionScanner ,由这个类来实现扫描包下的class和jar文件并把注解的Bean包装成BeanDefinition,
  3. 处理@ComponentScan、@import、@Bean等注解,生成BeanDefinition对象
  4. 将beanDefinition对象注册到Spring容器中。

至此,配置文件 到 BeanDefinition对象的转换结束。

重要方法三:finishBeanFactoryInitialization(beanFactory)

该方法作用:开始执行容器中的BeanDefinition对象 到Bean对象

先偷一张图:

 图片摘自spring bean生命周期详解,源码分析_李晨璐的博客-CSDN博客

这张图可以简化一下:

  1. createBeanInstance():例化bean对象,分配内存,属性值设置为默认值 ,实例化后的对象被封装在BeanWrapper对象中
  2. populateBean():用户自定义属性赋值,即Spring根据BeanDefinition中的信息 以及 通过BeanWrapper提供的设置属性的接口完成依赖注入。

  3. InvokeAwareMethods():将 Spring 内部对象注入到 Bean 中,如BeanFactory、ApplicationContext、Environment、ReosurceLoader

  4. 其实到此处,bean对象已经创建完成可以使用了。但是Spring的优秀之处就在于他留下了很多可扩展的接口。

  5. Bean的前置处理器:比如供dubbo框架扩展了@Service、@Reference注解的扫描

  6. InvokeInitMethods:执行初始化的调用方法,在java中基本没啥用,但是会检测当前的bean对象是否实现了InitializingBean接口,如果实现了,会提供afterPropertiesSet()方法

  7. Bean的后置处理器:后置处理器做了cglib和jdk代理的处理,固基于代理实现的aop可是看成是IOC的一个扩展

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/572154.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号