深入Spring源码解析---Spring-Bean的创建,以及Spring如何解决循环依赖问题

Spring是如何帮我维护Bean,如何进行IOC,如何解决循环依赖的呢?
Spring有两个很重要的入口类:一个是ClassPathXMLApplicationContext,另一个是AnnotationConfigApplicationContext,这个两个类都是扩展至AbstractApplicationContext这个类。构造上下文环境是都会调用到AbstractApplicationContext中的refresh方法,这个方法是Spring的核心方法。

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();
			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);
			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);
				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();
				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();
				// Initialize other special beans in specific context subclasses.
				onRefresh();
				// Check for listener beans and register them.
				registerListeners();
				// Instantiate all remaining (non-lazy-init) singletons.
				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();
			}
		}
	}

这个方法首先会创建一个BeanFactory对象,这个对象存放着所有Spring中所有的BeanDefinition对象,这个BeanDifinition对象其实就是让Spring按照我们的要求进行实例化的约束对象,它可以告诉Spring实例化对象是应该做什么。创建这个对象的过程其实就是解析Spring的xml文件,然后将解析结果封装成BeanDifinition对象,让后将这个封装好的BeanDifinition注册到BeanFactory里面。具体过程我之后会写一篇专门的博客进行解析。目前我们暂时不管,Spring实例化bean的入口是finishBeanFactoryInitialization(beanFactory)这个方法。在这个方法中会调用到beanFactory的preInstantiateSingletons()方法。这个方法里面里面会触发getBean(beanName)操作,这个getBean(beanName)操作就会触发bean的实例化。具体会调用到AbstractBeanFactory这个类里面的doGetBean()方法。
这个方法首先会去缓存中获取实例对象,这里就是Spring解决循环依赖的重点了,Spring采用了三级缓存的方式来解决循环依赖问题。第一次我们进到doGetBean方法中调用getSingleton(beanName)方法时,首先会去一级缓存(singletonObjects)中获取实例对象,获取不到我们会接着去二级缓存中获取实例对象(earlySingletonObjects)然后再获取不到那我们会从三级缓存中获取对象工厂,如果此时获取不到对象工厂,Spring就会返回一个空对象,如果获取到了工厂对象,我们就会从工厂对象里获取实例对象,并且把这个三级缓存中的beanName对应的对象工厂移除,并且把这个对象放入二级缓存中。

	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		//根据beanName从一级缓存中拿实例
		Object singletonObject = this.singletonObjects.get(beanName);
		//如果获取不到,同时判断这个beanName是否正在实例化
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				//从二级缓存中拿
				singletonObject = this.earlySingletonObjects.get(beanName);
				//二级缓存中没有,判断bean是否允许提前暴露
				if (singletonObject == null && allowEarlyReference) {
					//从三级缓存中拿到对象工厂
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						//从工厂中拿到对象
						singletonObject = singletonFactory.getObject();
						//升级到二级缓存
						this.earlySingletonObjects.put(beanName, singletonObject);
						//删除三级缓存
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

第一次Bean的实例肯定从缓存里获取不到对象,然后我们会判断BeanDefinition的一些特性,最主要的是判断BeanDefinition中的单例属性,绝大部分的BeanDefinition对象是单例,所以我们会调用到
getSingleton( beanName,singletonFactory)这个方法。这个方法首先还是从缓存中获取对象,如果获取成功则直接返回对象,获取失败,则需要进行实例化了。首先它会把BeanName加入到标识着正在实例化beanName的集合中(singletonsCurrentlyInCreation),同时把新创建的单例的标志位(newSingleton)置为false,之后就会调用到singletonFactory中的getObject()方法,这个方法会调用到AbstractAutowireCapableBeanFactory这个类中的createBean()方法,这个方法又会调用到doCreatebean(beanName,mbd,args(这个是null))方法。
这个方法首先会从调用 createBeanInstance(beanName, mbd, args) 进行创建实例化对象(大部分采用的是无参构造器进行创建,其他实例化过程比较复杂,有兴趣可以去看一下,本文以无参构造器为例),这个方法执行完后会返回一个BeanWrapper对象,这个对象主要是对Bean和Bean的Class类的封装,接着我们会执行到applyMergedBeanDefinitionPostProcessors()这个方法,这个方法主要做遍历BeanPostProcessor接口的实现类,找到实现了MergedBeanDefinitionPostProcessor这个接口的BeanDifinitionPostProcessor接口,然后调用他们的postProcessMergedBeanDefinition()方法,其中最主要的两个实现类为AutowireAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor这两个实现类,
AutowireAnnotationBeanPostProcessorProcessor这个类是对@Autowire注解的支持,主要是将Bean的Class对象进行解析,构造一个InjectionMetadata对象,这个对象可以理解为是需要实例化类的元数据对象,并把类中对应的属性构造成属性元数据 InjectionElement对象,构造完成后类的元数据对象放入injectionMetadataCache缓存中,通过封装为DI做准备。

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}

完成这些操作后,此时实例化对象堆中已经开辟了内存空间,但是属性值为空,此时Spring会将这个这个Bean加入到三级缓存中。接着就开始进行DI了,具体DI的入口方法是populateBean(beanName, mbd, instanceWrapper);这个也是对于BeanPostProcessor方法遍历,找到实现了InstantiationAwareBeanPostProcessor这个接口的对象,并且调用postProcessProperties(pvs, bw.getWrappedInstance(), beanName)这个方法。其实主要还是刚才两个类(AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor)中的方法调用。其中的最主要的就是遍历metadata对象中的InjectionElement集合,然后调用InjectionElement的injectinject(target, beanName, pvs)这个方法,CommonAnnotationBeanPostProcessor是通过这个方法调用到getResourceToInject(target, requestingBeanName)这个方法进而触发另外一个对象的getBean操作了。

	protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
			if (StringUtils.hasLength(this.beanName)) {
				if (beanFactory != null && beanFactory.containsBean(this.beanName)) {
					// Local match found for explicitly specified local bean name.
					//此处触发了另一个类的getBean操作
					Object bean = beanFactory.getBean(this.beanName, this.lookupType);
					if (requestingBeanName != null && beanFactory instanceof ConfigurableBeanFactory) {
						((ConfigurableBeanFactory) beanFactory).registerDependentBean(this.beanName, requestingBeanName);
					}
					return bean;
				}
				else if (this.isDefaultName && !StringUtils.hasLength(this.mappedName)) {
					throw new NoSuchBeanDefinitionException(this.beanName,
							"Cannot resolve 'beanName' in local BeanFactory. Consider specifying a general 'name' value instead.");
				}
			}
			// JNDI name lookup - may still go to a local BeanFactory.
			return getResource(this, requestingBeanName);
		}
	}

而AutowiredAnnotationBeanPostProcessor是通过调用
beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter)这个方法,然后通过这个方法触发属性的getBean()操作的。

@Override
		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
			Field field = (Field) this.member;
			Object value;
			if (this.cached) {
				value = resolvedCachedArgument(beanName, this.cachedFieldValue);
			}
			else {
				DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
				desc.setContainingClass(bean.getClass());
				Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
				Assert.state(beanFactory != null, "No BeanFactory available");
				TypeConverter typeConverter = beanFactory.getTypeConverter();
				try {
					//这里将会触发getBean的操作
					value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
				}
				catch (BeansException ex) {
					throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
				}
				synchronized (this) {
					if (!this.cached) {
						if (value != null || this.required) {
							this.cachedFieldValue = desc;
							registerDependentBeans(beanName, autowiredBeanNames);
							if (autowiredBeanNames.size() == 1) {
								String autowiredBeanName = autowiredBeanNames.iterator().next();
								if (beanFactory.containsBean(autowiredBeanName) &&
										beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
									this.cachedFieldValue = new ShortcutDependencyDescriptor(
											desc, autowiredBeanName, field.getType());
								}
							}
						}
						else {
							this.cachedFieldValue = null;
						}
						this.cached = true;
					}
				}
			}

			if (value != null) {
				ReflectionUtils.makeAccessible(field);
				field.set(bean, value);
			}
		}
	}

触发getBean()操作就会造成新的Bean的实例化过程。当整个过程完成后,会调用到AbstractAutowireCapableBeanFactory类中的initializeBean()这个方法,这个方法主要会完成bean实例化完成后的一些特殊操作,如SpringAOP 就是在这个方法中完成的,具体如果实现的可以看我另一篇博客。完成后会将Bean封装到DisposableBeanAdapter对象中,并把这个DisposableBeanAdapter对象添加到一个Map集合中。完成这些后会将Bean返回。返回bean后就要回到我么的DefaultSingletonBeanRegister这个类的getSlingleton方法中,然后将新建标志置为true,然后将这个BeanName从正在实例的集合(singletonsCurrentlyInCreation)中移除,并且将这个Bean加入到一级缓存中(singletonObjects)。至此基本完成了Bean的实例化。

具体流程图
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章