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的实例化。
具体流程图