Spring之IOC容器

容器的作用:1.少创建实例。2.垃圾回收。3.缓存快速获取。

Spring容器(Bean工厂)可简单分成两种:

  • BeanFactory:这是最基础、面向Spring的工厂类容器DefaultListableBeanFactory
  • ApplicationContext:这是在BeanFactory基础之上,面向使用Spring框架的开发者,提供了一系列的功能。默认情况下选择的是AnnotationConfigServletWebServerApplicationContext。

ApplicationContext & BeanFactory之间的关系:

  • 最基础BeanFactory工厂类之DefaultListableBeanFactory是由ApplicationContext的子类之GenericApplicationContext创建并持有的。
  • 容器的刷新也是由ApplicationContext的抽象子类AbstractApplicationContext触发的。
  • 容器刷新过程中由DefaultListableBeanFactory真正实现IOC容器的功能。
  • 用户能获取到的是ApplicationContext类型的容器。使用容器功能其实也是通过DefaultListableBeanFactory间接实现的。
  • 两者之间的桥梁之DefaultListableBeanFactory

IoC(Inversion of Control)控制反转,包含了两个方面:控制 & 反转。

  • 所谓的控制是指:当前对象对内部成员的控制权。
  • 所谓的反转是指:这种控制权不由当前对象管理了,由其他(类,第三方容器)来管理。

DI(dependency injection):对象的依赖关系将由系统中负责协调各对象的第三方组件在创建对象的时候进行设定,对象无需自行创建或管理它们的依赖关系,依赖关系将被自动注入到需要它们的对象当中去。

1、DefaultListableBeanFactory

DefaultSingletonBeanRegistry:是一个非常重要的接口,用于注册,获得,管理singleton对象。
其作用:

  • 负责管理singlenton对象。
  • 负责管理ObjectFactory对象。
  • 负责管理singleanton对象与ObjectFactory对象的 beanName。
  • 负责管理signleton状态中需要执行销毁流程的对象。
  • 负责需要管理@Dependent注解以及springboot里面的功能相同的注解产生的依赖关系与被依赖关系。、
  • 负责控制并发情况下销毁beanfactory。
  • 负责控制并发情况下只有一个线程注册同一个bean。
    在这里插入图片描述

1、DefaultListableBeanFactory#preInstantiateSingletons

public void preInstantiateSingletons(){
	for (String beanName : beanNames) {
		if (isFactoryBean(beanName)) {
		//AbstractBeanFactory#doGetBean
		}else{getBean(beanName);}
	}
}

2、AbstractBeanFactory

2.1、doGetBean

protected <T> T doGetBean(final String beanName, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly){
	Object sharedInstance = getSingleton(beanName);//3.1
	Object bean;
	if (sharedInstance != null && args == null) {// 从三级缓存中已经获取到beanName的实例【不完整】
		bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
	}else{// 首次创建beanName对应的实例
		//DefaultSingletonBeanRegistry#markBeanAsCreated
		markBeanAsCreated(beanName);
		sharedInstance = getSingleton(beanName, () -> {//3.2
			return createBean(beanName, mbd, args);//4.1
		}
	}
	return bean;
}

2.2、markBeanAsCreated

protected void markBeanAsCreated(String beanName) {
	if (!this.alreadyCreated.contains(beanName)) {
		synchronized (this.mergedBeanDefinitions) {
			if (!this.alreadyCreated.contains(beanName)) {
				clearMergedBeanDefinition(beanName);
				this.alreadyCreated.add(beanName);
			}
		}
	}
}

3、DefaultSingletonBeanRegistry

3.1、getSingleton

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	Object singletonObject = this.singletonObjects.get(beanName);
	//DefaultSingletonBeanRegistry#isSingletonCurrentlyInCreation
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {//首次创建条件均为false; 步骤3.2 才会保证该条件为TRUE
		synchronized (this.singletonObjects) {
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) {
			    // 4.2 已经将beanName对应的bean实例添加到三级缓存中
				ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
				if (singletonFactory != null) {
					//调用 4.3
					singletonObject = singletonFactory.getObject();
					this.earlySingletonObjects.put(beanName, singletonObject);
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}
	return singletonObject;
}
  • 首次创建beanName对应的bean实例时,该方法涉及的缓存均没有任何实例信息。
  • isSingletonCurrentlyInCreation标识当前单例bean是否处于创建过程中。
  • 在步骤4.4解决其bean对应的属性依赖时,同样触发AbstractBeanFactory#doGetBean,此时就从三级缓存singletonFactories获取beanName对应的实例信息,并且初始化到二级缓存earlySingletonObjects中。
  • 在循环依赖中,只有首次初始化的bean实例才会存在于二级缓存中。

优点:

类A引用B。B引用A,同时引用C。C引用A。创建bean时【实例化、初始化】根据字母排序依次进行。由此可知C实例创建最后进行,并且在执行4.4步骤时会优先实例A。由于B实例过程中其属性引用的A实例已经添加到二级缓存earlySingletonObjects,C实例直接从二级缓存获取,避免重复创建A实例。

3.2、getSingleton

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
	try{
		Object singletonObject = this.singletonObjects.get(beanName);
		beforeSingletonCreation(beanName);
		//2.1 createBean
		singletonObject = singletonFactory.getObject();// 该处返回的bean就是已经完全初始化后的完整bean
	}finally{
		//afterSingletonCreation
		afterSingletonCreation(beanName);//删除当前bean正在创建的标识
	}
	// #3.4
	addSingleton(beanName, singletonObject);
}
  1. singletonObject表示完成对空实例的属性赋值以及初始化。
  2. addSingleton将最终bean实例添加到IOC容器中。
public boolean isSingletonCurrentlyInCreation(String beanName) {
	return this.singletonsCurrentlyInCreation.contains(beanName);
}

protected void beforeSingletonCreation(String beanName) {
	if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
		throw new BeanCurrentlyInCreationException(beanName);
	}
}

protected void afterSingletonCreation(String beanName) {
	if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
		throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
	}
}

3.3、addSingletonFactory

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
	synchronized (this.singletonObjects) {
		if (!this.singletonObjects.containsKey(beanName)) {
			this.singletonFactories.put(beanName, singletonFactory);
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.add(beanName);
		}
	}
}

3.4、addSingleton

protected void addSingleton(String beanName, Object singletonObject) {
	synchronized (this.singletonObjects) {
		this.singletonObjects.put(beanName, singletonObject);
		this.singletonFactories.remove(beanName);
		this.earlySingletonObjects.remove(beanName);
		this.registeredSingletons.add(beanName);
	}
}

普通bean实例完成后,也是在此处将三级缓存中的对象删除,最终存放到一级缓存中。

4、AbstractAutowireCapableBeanFactory

真正创建bean实例、实例属性赋值、初始化的核心类。

4.1、createBean

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
	// aop 相关的后置处理器~InstantiationAwareBeanPostProcessor
	// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
	Object bean = resolveBeforeInstantiation(beanName, mbd);
	if (bean != null) {
		return bean;
	}
	return doCreateBean(beanName, mbdToUse, args);
}
  • Apply before-instantiation post-processors, resolving whether there is a before-instantiation shortcut for the specified bean。
  • 此处 InstantiationAwareBeanPostProcessor后置处理器接口的作用是允许在创建目标bean实例之前取而代之生成其代理对象。【切面相关逻辑

resolveBeforeInstantiation只是针对有自定义的targetsource,因为自定义的targetsource不是spring的bean那么肯定不需要进行后续的一系列的实例化初始化。所以可以在resolveBeforeInstantiation直接进行。创建代理对象是在初始化以后调后置处理器的方法实现的。

4.1.1、bbp之InstantiationAwareBeanPostProcessor

如果此时处理@Aspect注解,此时的beanPostProcessor为AnnotationAwareAspectJAutoProxyCreator
在这里插入图片描述

4.2、三级缓存&创建空实例doCreateBean

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args){
	// 通过反射创建实例
	BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);
	boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
			isSingletonCurrentlyInCreation(beanName));
	Object bean = instanceWrapper.getWrappedInstance();
	// Allow post-processors to modify the merged bean definition		
	//处理MergedBeanDefinitionPostProcessor后置处理器
	applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
	if (earlySingletonExposure) {
		//3.3 添加三级缓存
		addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
	}
	populateBean(beanName, mbd, instanceWrapper);
	Object exposedObject = initializeBean(beanName, exposedObject, mbd);
	if (earlySingletonExposure) {//true
		// 调用3.1  对于循环依赖,首次初始化的实例在二级缓存中是存在的,二级缓存有且仅有首次初始化的实例
		Object earlySingletonReference = getSingleton(beanName, false);
		if (earlySingletonReference != null) {
			if (exposedObject == bean) {
				//疑问1:为啥存在这一步?猜测两者引用是一样的,交换与否没有影响
				exposedObject = earlySingletonReference;
			}else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
				String[] dependentBeans = getDependentBeans(beanName);
				Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
				for (String dependentBean : dependentBeans) {
					if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
						actualDependentBeans.add(dependentBean);
					}
				}
			}
		}
	}
	registerDisposableBeanIfNecessary(beanName, bean, mbd);
	return exposedObject;
}
  • 根据RootBeanDefinition创建实例bean BeanWrapper
  • 执行MergedBeanDefinitionPostProcessor后置处理器相关功能。
  • 添加三级缓存singletonFactories

备注:疑问1

因为二级缓存存在的实例earlySingletonReference可能是代理对象。exposedObject一定是通过反射创建的空的实例对象。引用重置是为了保证其他实例对当前实例的引用与IOC容器当前实例的引用是一致的,要不都是代理对象,要不都是正常发射获取的实例对象。

4.2.1、bdpp之applyMergedBeanDefinitionPostProcessors后置处理器

4.3、getEarlyBeanReference

/**
 *  Obtain a reference for early access to the specified bean,
 * typically for the purpose of resolving a circular reference.
 */
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【尚未初始化】或者其代理对象【】。

4.4、bean属性赋值

public abstract class AbstractAutowireCapableBeanFactory{

	protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						continueWithPropertyPopulation = false;
						break;
					}
				}
			}
		}
	
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				// AutowiredAnnotationBeanPostProcessor通过注解Autowired获取其依赖实例引用
				PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
				pvs = pvsToUse;
			}
		}
		if (pvs != null) {
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}
}

4.5、bean的初始化

public abstract class AbstractAutowireCapableBeanFactory{
	protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		invokeAwareMethods(beanName, bean);//执行接口Aware核心方法
		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}
		invokeInitMethods(beanName, wrappedBean, mbd);//接口InitializingBean、自定义的init方法
		if (mbd == null || !mbd.isSynthetic()) {//触发aop、事务涉及的目标bean代理功能
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}
}

Spring IOC容器创建元素bean时所谓的初始化就是指执行:接口Aware、InitializingBean核心方法、自定义的init方法以及BeanPostProcessors后置处理器两个核心方法。

涉及到后置处理器

  1. 步骤4.1中的后置处理器InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation。【创建实例之前】
  2. 步骤4.2中的后置处理器MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition。【创建实例之后,属性赋值之前】
  3. 步骤4.4中的后置处理器InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation。【创建实例之后,属性赋值之前】
  4. 步骤4.4中的后置处理器InstantiationAwareBeanPostProcessor#postProcessProperties。【涉及解析注解Autowired,处理属性赋值】
  5. 步骤4.5中的后置处理器。【初始化过程中默认执行全部的后置处理器】

参考文章

依赖注入

依赖类不由程序员通过 new 方式直接实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中。依赖注入的另一种说法是“控制反转”,通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员,而控制反转是指new实例工作不由我们程序员来做而是交给spring容器来做。
依赖注入方式:

  1. set注入
  2. 构造器注入
  3. 静态工厂的方法注入
  4. 实例工厂的方法注入

自动装配

有五种自动装配的方式,可以用来指导Spring容器用自动装配方式来进行依赖注入。

  1. no:默认的方式是不进行自动装配,通过显式设置ref属性来进行装配。
  2. byName:通过参数名自动装配,Spring容器在配置文件中发现bean的autowire属性被设置成byname,之后容器试图匹配、装配和该bean的属性具有相同名字的bean。
  3. byType::通过参数类型自动装配,Spring容器在配置文件中发现bean的autowire属性被设置成byType,之后容器试图匹配、装配和该bean的属性具有相同类型的bean。如果有多个bean符合条件,则抛出错误。
  4. constructor:这个方式类似于byType,但是要提供给构造器参数,如果没有确定的带参数的构造器参数类型,将会抛出异常。
  5. autodetect:首先尝试使用constructor来自动装配,如果无法工作,则使用byType方式。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值