Spring循环依赖源码解析

Spring循环依赖场景有构造器循环依赖(不可解决),set注入循环依赖(单例可以解决)。
解决大概逻辑
在这里插入图片描述
主要代码

public class LagouBean implements InitializingBean, ApplicationContextAware {

	private ItBean itBean;
	public void setItBean(ItBean itBean) {
		System.out.println("setItBea..........");
		this.itBean = itBean;
	}
	/**
	 * 构造函数
	 */
	public LagouBean(){
		System.out.println("LagouBean 构造器...");
	}
	/**
	 * InitializingBean 接口实现
	 */
	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("LagouBean afterPropertiesSet...");
	}

	public void print() {
		System.out.println("print方法业务逻辑执行");
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		System.out.println("setApplicationContext....");
	}
}


public class ItBean {

	private LagouBean lagouBean;
	public void setLagouBean(LagouBean lagouBean) {
		System.out.println("setLagouBean.............");
		this.lagouBean = lagouBean;
	}
	/**
	 * 构造函数
	 */
	public ItBean(){
		System.out.println("ItBean 构造器...");
	}
}

// 测试类
@Test
	public void testIoC() {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
		LagouBean lagouBean = applicationContext.getBean(LagouBean.class);
		System.out.println(lagouBean);
	}

源码分析
1、首先进入 org.springframework.context.support.AbstractApplicationContext#refresh 的 finishBeanFactoryInitialization

2、实例化所有剩余的(非延迟初始化)单例,进入org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons 的 getBean(beanName)

3、doGetBean(name, null, null, false);

4、org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean 的 return createBean(beanName, mbd, args);

5、创建bean,并放入三级缓存中org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean 的 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

6、属性填充 populateBean(beanName, mbd, instanceWrapper);

7、 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean 的 applyPropertyValues(beanName, mbd, bw, pvs);

8、注入所需要的类B
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyPropertyValues 的 Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);

9、 org.springframework.beans.factory.support.BeanDefinitionValueResolver#resolveReference的 bean = this.beanFactory.getBean(refName);
这时候就会创建B,初始化B之后会把B放到三级缓存中,属性注入时候会去缓存中获取A,这时候可以在三级缓存中获取到A,注入A并把二级缓存,B注入A完成之后放到一级缓存中,这时候接着类A属性注入B,在缓存中获取到B直接注入,并放到一级缓存中,至此结束

之后的代码基本是上面这些,只不过类B注入类A时候从缓存中获取 org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
Object sharedInstance = getSingleton(beanName);

// 
@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 1 刷新前的预处理
			prepareRefresh();

			// 2 获取 beanFactory
			//   加载 BeanDefition 注册到 BeanDefitionRegistry
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// 3 BeanFactory 的预准备工作(BeanFactory进行一些设置,比如context的类加载器)
			prepareBeanFactory(beanFactory);

			try {
				// 4 BeanFactory 准备工作完成后进行的后置处理工作
				postProcessBeanFactory(beanFactory);

				// 5 实例化实现了BeanFactoryPostProcessor接口的bean,并调用接口
				invokeBeanFactoryPostProcessors(beanFactory);

				// 6 注册 BeanPostProcessor(bean 后置处理器),在创建bean的前后执行
				registerBeanPostProcessors(beanFactory);

				// 7 初始化MessageSource组件
				initMessageSource();

				// 8 初始化事件派发器
				initApplicationEventMulticaster();

				// 9 子类重写这个方法,在容器刷新的时候可以自定义逻辑
				onRefresh();

				// 10 注册应用的监听器 就是注册实现了ApplicationListener接⼝的监听器 bean
				registerListeners();

				// 11 初始化所有剩下的非懒加载的单例bean,初始化创建非懒加载方式的单例bean实例(未设置属性)
				// 		填充属性,初始化方法调用(afterPropertoesSet方法,init-method方法)调用BEanPostProcessor 对实例bean进行后置处理
				finishBeanFactoryInitialization(beanFactory);

				// 12 完成context的刷新,主要是调用LifecycleProcessor 的 onRefresh 方法,并且发布事件 ContextRefreshedEvent
				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();
			}
		}
	}

2、getBean(beanName)

// 以下仅粘贴主要代码
public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}

		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						final FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
											((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				else {
					// 进入到这里获取bean
					getBean(beanName);
				}
			}
		}

	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值