容器的作用:1.少创建实例。2.垃圾回收。3.缓存快速获取。
三级缓存 & 循环依赖
三级缓存的设计主要是为了解决循环依赖的问题。
备注:循环依赖过程中只有uc 涉及1、3级缓存。image创建涉及了1、2、3级缓存。
/** Cache of singleton objects: bean name --> bean instance 1级缓存*/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name --> ObjectFactory 3级缓存*/
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name --> bean instance 2级缓存*/
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
三级缓存存在的必要性
一级缓存不能解决循环依赖:如果只有一级缓存,则意味着实例完全状态(实例 + 属性填充)和非完全状态(创建实例尚未属性填充)都存在一级缓存中,此时获取的对象可能是非完全状态的实例。该情况可以通过二级缓存解决。
singletonFactories的必要性:
- 步骤4.3中主要是用来处理当前空实例是否需要代理处理。
- 一定是延迟加载,所谓的延迟加载就是处理当前bean的属性依赖类时才会执行步骤4.3对应的方法。
-
场景:类A是需要代理的类。类B、类C等都引用了类A。如果只有二级缓存则意味着实例化B、C过程中都会触发类A代理的执行,并且生成的类A都是不同的实例。导致的缺点就是
频繁创建同一个类A
以及
不同实例【B、C等】引用的属性类A其实例是不一样的
,这是严重不允许的。三级缓存可以缓存类A的代理对象,保证类B、类C实例化时获取到同一个类A的代理对象。 - 需要的类有可能是简单对象,也有可能是需要代理的对象(AOP),当我们向三级缓存放置匿名内部类时可以在获取的时候决定是简单对象还是代理对象,这就是三级缓存存在的意义。
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);
}
- singletonObject表示完成对空实例的属性赋值以及初始化。
- 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、populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
boolean continueWithPropertyPopulation = true;
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);
}
}
- 此处涉及两处BeanPostProcessor后置处理器执行,具体的后置处理器均是接口InstantiationAwareBeanPostProcessor的子类。
- 第二处后置处理器对应的AutowiredAnnotationBeanPostProcessor就是解析当前bean中的注解Autowired,从而初始化当前bean的属性。
4.4.1、bpp之InstantiationAwareBeanPostProcessor后置处理器
如果当前bean存在注解Autowired,则由AutowiredAnnotationBeanPostProcessor后置处理器触发依赖引用的解析。
4.5、initializeBean
该方法执行前beanName对应实例的引用依赖已经赋值完毕【此时的
引用依赖
只是简单类实例,尚未属性赋值以及后续的初始化initializeBean】。进一步完成初始化。
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
invokeAwareMethods(beanName, bean);
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
invokeInitMethods(beanName, wrappedBean, mbd);
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
- 当前bean实例实现接口Aware,则调用Aware相关接口的AwareMethod。
- 调用默认全部的BeanPostProcessors处理当前bean。
- 如果当前bean实现接口InitializingBean,则回调其默认方法afterPropertiesSet。
- 调用自定义的InitMethod方法等。
4.5.1、bbp之全部后置处理器
执行#10全部的后置处理器的applyBeanPostProcessorsBeforeInitialization、applyBeanPostProcessorsAfterInitialization。
参考文章:
循环依赖
涉及到后置处理器
- 步骤4.1中的后置处理器InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation。【创建实例之前】
- 步骤4.2中的后置处理器MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition。【创建实例之后,属性赋值之前】
- 步骤4.4中的后置处理器InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation。【创建实例之后,属性赋值之前】
- 步骤4.4中的后置处理器InstantiationAwareBeanPostProcessor#postProcessProperties。【涉及解析注解Autowired,处理属性赋值】
- 步骤4.5中的后置处理器。【初始化过程中默认执行全部的后置处理器】
依赖注入
依赖类不由程序员通过 new 方式直接实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中。依赖注入的另一种说法是“控制反转”,通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员,而控制反转是指new实例工作不由我们程序员来做而是交给spring容器来做。
依赖注入方式:
- set注入
- 构造器注入
- 静态工厂的方法注入
- 实例工厂的方法注入
自动装配
有五种自动装配的方式,可以用来指导Spring容器用自动装配方式来进行依赖注入。
- no:默认的方式是不进行自动装配,通过显式设置ref属性来进行装配。
- byName:通过参数名自动装配,Spring容器在配置文件中发现bean的autowire属性被设置成byname,之后容器试图匹配、装配和该bean的属性具有相同名字的bean。
- byType::通过参数类型自动装配,Spring容器在配置文件中发现bean的autowire属性被设置成byType,之后容器试图匹配、装配和该bean的属性具有相同类型的bean。如果有多个bean符合条件,则抛出错误。
- constructor:这个方式类似于byType,但是要提供给构造器参数,如果没有确定的带参数的构造器参数类型,将会抛出异常。
- autodetect:首先尝试使用constructor来自动装配,如果无法工作,则使用byType方式。