• Spring源码分析之循环引用


    前言

    循环引用又叫循环依赖,比如A依赖B,B又依赖A,Spring不支持构造器注入方式的循环依赖,支持属性注入的循环依赖。
    这里关注的情况是Bean都是singleton(单例),对于prototype(原型)的情况,暂时不管。

    构造器注入

    这里为了分析原理,没有使用强大的ApplicationContext,使用了底层的DefaultListableBeanFactory实现(IOC容器实现)。
    ApplicationContext会帮我们自动添加很多的BeanPostProcessor,如AutowiredAnnotationBeanPostProcessor,
    源码可以查看AnnotationConfigUtils的registerAnnotationConfigProcessors()方法。这里我们手动添加AutowiredAnnotationBeanPostProcessor对象,
    AutowiredAnnotationBeanPostProcessor不仅会处理@Autowired和@Value注解,处理属性注入,还会查找最合适的构造器,使用它来实例化对象。

    import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    
    public class TestCircleReference {
    
      public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder
            .genericBeanDefinition(UserService.class);
        beanFactory.registerBeanDefinition("userService", definitionBuilder.getBeanDefinition());
        definitionBuilder = BeanDefinitionBuilder
            .genericBeanDefinition(AddressService.class);
        beanFactory.registerBeanDefinition("addressService", definitionBuilder.getBeanDefinition());
        //AutowiredAnnotationBeanPostProcessor不仅会处理@Autowrired注解,还会在创建Bean时选择最合适的构造器
        AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
        autowiredAnnotationBeanPostProcessor.setBeanFactory(beanFactory);
        beanFactory.addBeanPostProcessor(autowiredAnnotationBeanPostProcessor);
        UserService userService = (UserService) beanFactory
            .getBean("userService");
        userService.users();
      }
    
      public static class AddressService {
    
        private UserService userService;
    
        public AddressService(UserService userService) {
          this.userService = userService;
        }
      }
    
      public static class UserService {
    
        private AddressService addressService;
    
        public UserService(AddressService addressService) {
          this.addressService = addressService;
        }
    
        public void users() {
          System.out.println(addressService.getClass());
        }
      }
    }
    

    上述代码我们定义了两个Bean,UserService和AddressService,两者相互依赖,且都是构造器注入。Spring会抛出异常,不支持这种情况下的循环依赖。

    Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'userService': Requested bean is currently in creation: Is there an unresolvable circular reference?
    

    属性注入

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    
    public class TestCircleReference2 {
    
      public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder
            .genericBeanDefinition(UserService.class);
        beanFactory.registerBeanDefinition("userService", definitionBuilder.getBeanDefinition());
        definitionBuilder = BeanDefinitionBuilder
            .genericBeanDefinition(AddressService.class);
        beanFactory.registerBeanDefinition("addressService", definitionBuilder.getBeanDefinition());
        //AutowiredAnnotationBeanPostProcessor不仅会处理@Autowrired注解,还会在创建Bean时选择最合适的构造器
        AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
        autowiredAnnotationBeanPostProcessor.setBeanFactory(beanFactory);
        beanFactory.addBeanPostProcessor(autowiredAnnotationBeanPostProcessor);
        UserService userService = (UserService) beanFactory
            .getBean("userService");
        userService.users();
      }
    
      public static class AddressService {
    
        @Autowired
        private UserService userService;
      }
    
      public static class UserService {
    
        @Autowired
        private AddressService addressService;
    
        public void users() {
          System.out.println(addressService.getClass());
        }
      }
    }
    

    可以正常运行,说明Spring支持属性注入这种情况下的循环依赖。

    原理分析

    Bean生命周期基本如下

    以上述的UserService和AddressService为例,UserService实例化之后,注入AddressService属性时,发现容器中还没有,需要先创建,但创建AddressService的过程中又需要注入UserService,但此时UserService还没有创建完成,所以就出问题了。
    一个简单的解决方案为:

    1. UserService实例化,将此时(还没有完全创建成功)的对象保存到一个中间缓存中
    2. 注入AddressService
    3. 实例化AddressService,注入UserService,从中间缓存中取,AddressService创建完成
    4. UserService创建完成

    之前的结构

    添加缓存之后的结构

    按理来说,加一层缓存已经可以解决问题,Spring为什么使用了两层缓存呢,这是因为实例化时的UserService和最终创建完成的UserService可能不是同一个对象,
    Spring提供了BeanPostProcessor来对实例化后的Bean进行加工,AOP(面向切面编程)就是使用AnnotationAwareAspectJAutoProxyCreator对原始Bean对象进行加工,
    创建代理对象的,所以Spring使用两层缓存来解决这个问题。

    源码分析

    我们在Spring源码分析之Bean生命周期 基础上继续分析Spring对循环依赖的处理。

    public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    
    	//保存创建完成的Bean
    	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    
    	//保存实例化之后的Bean和对应的后续操作(根据此Bean加工包装)
    	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
    
    	//保存加工包装之后的Bean
    	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
    }
    

    一个Bean对象只可能存在于在上述3个Map中的一个,Bean状态转换的过程也就是在不同Map间切换的过程。
    继续分析getBean("userService")的执行流程,进入AbstractBeanFactory类,主要关注对循环依赖的处理

    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
    			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
                    //处理FactoryBean类型的Bean名称,暂时不管
    		final String beanName = transformedBeanName(name);
    		Object bean;
    		//查看是否已经创建过(从单例池中查询),处理循环依赖的核心方法
    		Object sharedInstance = getSingleton(beanName);
    		if (sharedInstance != null && args == null) {
                            
    		}
    		else {
    			try {
                                    //上面已经说了,DefaultListableBeanFactory也实现了BeanDefinitionRegistry,所以也管理BeanDefinition,这里根据Bean名称查询出之前注册的BeanDefinition
    				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    				//创建单例Bean
    				if (mbd.isSingleton()) {
                                            //创建完成之后会将Bean放到单例池(singletonObjects)中,下次直接从池中取就可以了
    					sharedInstance = getSingleton(beanName, () -> {
    						try {
                                                            //真正创建Bean的地方
    							return createBean(beanName, mbd, args);
    						}
    					});
    				}
    			}
    		}
    		return (T) bean;
    	}
    
    

    核心方法为getSingleton(beanName),此方法为DefaultSingletonBeanRegistry提供,从名字就可以看出来是处理单例Bean相关的。

    @Override
    @Nullable
    public Object getSingleton(String beanName) {
    	return getSingleton(beanName, true);
    }
    @Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
                    //先查询singletonObjects,能查到,说明该Bean已经完全创建成功了
    		Object singletonObject = this.singletonObjects.get(beanName);
    		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    			synchronized (this.singletonObjects) {
                                    //执行到这,说明Bean还没有完全创建完成,只是进行了实例化,还没有装配属性
    				singletonObject = this.earlySingletonObjects.get(beanName);
    				if (singletonObject == null && allowEarlyReference) {
    					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
    					if (singletonFactory != null) {
                                                    //执行后续对Bean的加工(如创建代理对象),后续分析可以看到ObjectFactory的具体逻辑
    						singletonObject = singletonFactory.getObject();
    						this.earlySingletonObjects.put(beanName, singletonObject);
    						this.singletonFactories.remove(beanName);
    					}
    				}
    			}
    		}
    		return singletonObject;
    	}
    

    继续分析真正创建Bean的流程

    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    			throws BeanCreationException {
    		try {
    			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    			return beanInstance;
    		}
    	}
    
    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
    			throws BeanCreationException {
    		//创建Bean实例
    		BeanWrapper instanceWrapper = null;
    		if (instanceWrapper == null) {
                            //创建Bean实例,会找到最合适的构造器,通过反射创建对象
    			instanceWrapper = createBeanInstance(beanName, mbd, args);
    		}
    		final Object bean = instanceWrapper.getWrappedInstance();
    		Class<?> beanType = instanceWrapper.getWrappedClass();
    		if (beanType != NullBean.class) {
    			mbd.resolvedTargetType = beanType;
    		}
    		//解决循环依赖相关,BeanFactory提供了一个属性allowCircularReferences,表示是否允许循环依赖,默认允许
    		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
    				isSingletonCurrentlyInCreation(beanName));
    		if (earlySingletonExposure) {
                            //处理循环依赖的核心
    			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    		}
    		//初始化Bean实例
    		Object exposedObject = bean;
    		try {
                            //Bean属性装配,AutowiredAnnotationBeanPostProcessor就是在这里被调用来处理@Autowired和@Value注解的
    			populateBean(beanName, mbd, instanceWrapper);
                            //初始化Bean
    			exposedObject = initializeBean(beanName, exposedObject, mbd);
    		}
    		return exposedObject;
    	}
    

    继续addSingletonFactory()方法

    protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
                    //对singletonFactories的处理,添加一个Bean对应的后续操作,具体就是getEarlyBeanReference()方法
    		synchronized (this.singletonObjects) {
    			if (!this.singletonObjects.containsKey(beanName)) {
    				this.singletonFactories.put(beanName, singletonFactory);
    				this.earlySingletonObjects.remove(beanName);
    				this.registeredSingletons.add(beanName);
    			}
    		}
    	}
    

    分析getEarlyBeanReference()做的操作

    protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    		Object exposedObject = bean;
    		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    			for (BeanPostProcessor bp : getBeanPostProcessors()) {
    				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
    					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                                            //核心
    					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
    				}
    			}
    		}
    		return exposedObject;
    	}
    

    根据一个Bean获取它的加工之后的对象,暂时只有一个具体的实现类AbstractAutoProxyCreator,就是AOP的实现。

    分析总结

    getBean("userService")的流程:

    1. 在singletonObjects中查询userService对应的Bean实例,没有找到,查找singletonFactories,也没有找到,实例化一个。
    2. 向singletonFactories中添加一个ObjectFactory对象,具体的操作为根据此Bean获取加工之后的对象。
    3. 注入addressService属性,此时singletonObjects中也不包含addressService对应的Bean。
    4. 实例化AddressService,注入userService属性,查找singletonObjects,不存在,查找singletonFactories,存在,执行对应的逻辑(getEarlyBeanReference()方法,获取加工之后的对象),将加工后的对象放到earlySingletonObjects中,并删除singletonFactories中的。
    5. addressService对应的Bean创建完成,添加到singletonObjects中,并删除earlySingletonObjects中的。
    6. addressService注入到userService对应的Bean中,userService对应的Bean也创建完成,添加到singletonObjects中,并删除earlySingletonObjects中的。
    7. 返回userService对应的Bean。

    上述的对一个对象进行加工可以简单看做创建一个代理对象,earlySingletonObjects中存储的就是代理对象(此时还没有装配属性)。对于一个更加复杂的依赖关系更能体现出earlySingletonObjects的作用。
    A依赖B和C,B和C都依赖A,依据上述的流程,B在注入A属性的过程会创建A的代理对象,放到earlySingletonObjects中,后续C注入A属性的时候,直接就可以从earlySingletonObjects中取,不需要再次走创建代理的流程,也保证了是A的同一个代理对象。

    • singletonFactories,保存的是ObjectFactory对象,将原始Bean(未加工,未装配属性)和加工过程封装了起来,可以看做一个闭包对象,或者看做一个匿名内部类
    • earlySingletonObjects,保存创建的代理对象(未装配属性)
    • singletonObjects,保存创建完成的对象(还是之前的代理对象,但是已装配属性)

    注意,上述的装配属性是一个简写,实际还包含Aware钩子方法的回调,BeanPostProcessor的处理,初始化方法的调用等步骤。

    参考

    Spring中的循环依赖及解决

  • 相关阅读:
    线段树(updata+query)
    铁轨(栈)
    困难的串(搜索)
    素数环(简单搜索)
    编码
    opencv + numpy for python
    PIL参考手册
    八数码问题
    三维地图(BFS)
    梯田(dfs)
  • 原文地址:https://www.cnblogs.com/strongmore/p/16223023.html
Copyright © 2020-2023  润新知