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