spring内幕(六)bean的初始化过程和循环依赖的解决

本文详细探讨了Spring框架中bean的初始化过程,包括在`finishBeanFactoryInitialization`方法和`getBean`方法中的初始化触发。重点讲解了`preInstantiateSingletons`方法的执行步骤,以及在`getBean`实现中的依赖注入和循环依赖解决方案。Spring通过单例缓存的三级结构处理单例bean的循环依赖问题,对于非单例bean的循环依赖则抛出异常。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在上一篇,记录了ioc容器的初始化,当ioc容器初始化之后,里面保存了BeanDefinition的信息,但此时 bean还不存在。

初始化bean有两个地方触发,一个是在容器的初始化的refresh方法里面的 finishBeanFactoryInitialization(beanFactory) 方法
该方法里面其实也是调用了getBean()

	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();


			//该方法创建一个ioc容器 并加载xml中的资源转为beanDefinition对象填充进去
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
		
				//设置beanFactory的后置处理
				postProcessBeanFactory(beanFactory);

	
				//调用beanFactory的后置处理器 这些后置处理器是在beanDefinition中向容器注册的
				invokeBeanFactoryPostProcessors(beanFactory);

			
				//注册bean的后置处理器 在bean的创建过程中调用
				registerBeanPostProcessors(beanFactory);

				
				//对上下文中的消息源进行初始化
				initMessageSource();

			
				//初始化上下文的事件机制
				initApplicationEventMulticaster();

			

				//始化其他特殊的bean  比如说springboot里面内置的tomcat
				onRefresh();

			
				//检查监听bean 并将这些bean向容器注册
				registerListeners();

			
				//实例化所有不是懒加载的单例bean
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				//发布容器事件,接收refresh过程
				finishRefresh();
			}

另一个地方就是ioc的getBean()方法,第一次调用这个方法获取这个bean的时候,如果这个bean没有被创建的话,就会触发bean的初始化。

先看下 finishBeanFactoryInitialization(beanFactory) 方法,
这个方法 会先获取所有实现了LoadTimeWeaverAware接口的bean的名字,然后挨个调用getBean方法进行初始化,最后调用 beanFactory.preInstantiateSingletons();初始化其他 单例非懒加载的类型的bean

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {

		//先初始化ConversionService这个bean
		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
			beanFactory.setConversionService(
					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
		}

		// Register a default embedded value resolver if no bean post-processor
		// (such as a PropertyPlaceholderConfigurer bean) registered any before:
		// at this point, primarily for resolution in annotation attribute values.
		//如果没有设置后置处理器,那么就设置默认的嵌入值解析器 用于解析注解的属性值
		if (!beanFactory.hasEmbeddedValueResolver()) {
			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
		}

		// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
		//获取所有可以提前加载的bean的名字 实现了LoadTimeWeaverAware接口的bean 用于需要被初始化阶段就能收到容器的通知的bean 
		//比如说tomcat有这个需求 
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			//todo 核心方法 加载这些可以提前加载的bean的名字
			getBean(weaverAwareName);
		}

		// Stop using the temporary ClassLoader for type matching.
		beanFactory.setTempClassLoader(null);

		// Allow for caching all bean definition metadata, not expecting further changes.
		beanFactory.freezeConfiguration();

		// Instantiate all remaining (non-lazy-init) singletons.
		//todo  实例化 单例非懒加载的类型
		beanFactory.preInstantiateSingletons();
	}

看下preInstantiateSingletons方法

1.获取所有的beanNames ,beanDefinitionNames里面按顺序存储了所有的beanDefinition的beanNames
2.触发 所有的 非懒加载的单例bean 挨个进行初始化
3.通过beanName获取BeanDefinition ,该方法会从父容器和子容器合并集合中查找BeanDefinition
4.如果 BeanDefinition 非抽象,是单例 且非懒加载 那么继续下一个流程 否则忽略
5.检查是否是FactoryBean类型 如果不是 ,直接跳转到调用getBean
6. 判断是FactoryBean 调用getBean( FACTORY_BEAN_PREFIX + beanName) Bea

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值