SpringBoot源码(⼗四):spring三级缓存源码,解决循环依
赖
介绍
在写springboot项⽬时,我们对于bean的注⼊都使⽤注解的⽅式进⾏注⼊。可以根据field注⼊,set⽅法注⼊还有构造器⽅法注⼊。但是我们都写过类似下⾯的代码:
@Service
public class Bean1 {
@Autowired
private Bean2 bean2;
}
@Service
public class Bean2 {
@Autowired
private Bean1 bean1;
}
即Bean1和Bean2互相引⽤,但是也没有出异常。
这是怎么回事呢?
其实主要原因时spring替我们处理了,处理的⽅式就是我们要说的三级缓存。但是为什么三级缓存⽆法解决构造器循环依赖呢?接下来通过源码来⼀⼀解答。
源码
在看源码之前先来介绍下什么是三级缓存,其实上⼀篇介绍的⽅法时候已经说过了,这⾥再提⼀下
1. singletonObjects为⼀级缓存,我们实例化的bean都在这个map⾥,侠义的说singletonObjects才是我们真正的spring容器,存放bean的地⽅。
2. earlySingletonObjects为⼆级缓存,是存放未完成的bean的缓存,如果有代理的话,存放的是代理
对象。
3. singletonFactories为三级缓存,存放的是⼀个ObjectFactory,数据通过getObject⽅法获得。
说完三级缓存的⼤概作⽤,来介绍下三级缓存的使⽤吧。其中有些需要涉及到spring获取bean的⽅法,不了解的话可以看下的⼤致流程。⾸先从获取bean开始看吧
获取bean时三级缓存的应⽤
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// 从三级缓存中获取
Object sharedInstance = getSingleton(beanName);
/**
* 省略代码
*/
}
@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从⼀级缓存中获取
Object singletonObject = (beanName);resource和autowired注解的区别
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 从⼆级缓存中获取
singletonObject = (beanName);
if (singletonObject == null && allowEarlyReference) {
// 从三级缓存中获取
ObjectFactory<?> singletonFactory = (beanName);
if (singletonFactory != null) {
singletonObject = Object();
this.earlySingletonObjects.put(beanName, singletonObject);
ve(beanName);
}
}
}
}
return singletonObject;
}
在获取bean的时候,最开始我们会先从三级缓存中获取,如果获取不到,才会去创建bean。创建bean时,第三级缓存应⽤
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = ve(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = WrappedInstance();
Class<?> beanType = WrappedClass();
if (beanType != NullBean.class) {
}
/**
* 省略代码
*/
// 第三级缓存
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
}
}
/**
* 省略代码
*/
return exposedObject;
}
⾸先省略了⼀些暂时不需要的代码,看下实例化bean之后加⼊三级缓存部分。
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 加⼊到三级缓存中
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
if (!ainsKey(beanName)) {
// 加⼊到三级缓存中
this.singletonFactories.put(beanName, singletonFactory);
// 删除⼆级缓存
ve(beanName);
// 加⼊注册bean的set中
}
}
}
这部分代码就是把创建的bean封装成ObjectFactory对象,加⼊到三级缓存中,并且删除⼆级缓存。现在三级缓存就有了,只不过是封装成了ObjectFactory对象。
接下来就要查那些需要被注⼊的bean了。⽐如上⾯举例的Bean1,在实例化Bean1之后,还需要去把Bean2注⼊到Bean1中。
那么可以想象下接下来的流程,那就是去到Bean2,并且实例化Bean2,并且把Bean2注⼊到Bean1,并且作为Bean1的field。
既然⼤致的流程已经知道了,看看spring中的实现吧。实现就在populateBean中。
populateBean填充bean属性
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 封ean的对象为空,则进⾏⼀些处理和验证
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
}
else {
// Skip property population phase for null instance.
return;
}
}
boolean continueWithPropertyPopulation = true;
// 看代码逻辑应该是可以实现InstantiationAwareBeanPostProcessor
// ⾃定义去实现注⼊属性的逻辑,这样就不⽤再去⾛spring⾃⼰的⽅式去查需要注⼊的bean
/
/ 和注⼊⽅式了
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.WrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
}
if (!continueWithPropertyPopulation) {
return;
}
PropertyValues pvs = (mbd.hasPropertyValues() ? PropertyValues() : null);
// 根据名称注⼊还是根据类型注⼊
if (ResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称注⼊
if (ResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据类型注⼊
if (ResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (DependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
if (pvs == null) {
pvs = PropertyValues();
}
// java⾃省,到那些⾃省规范的属性,然后排除掉spring忽略的
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 根据注解注⼊
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
if (pvs != null) {
// 将属性应⽤到bean上
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
populateBean是查bean中的属性,到需要注⼊的属性。然后设置到bean上。来梳理下populateBean的流程。
1. 检查包ean的包装对象是不是空,是空话判断是不是有需要注⼊的属性,如果有则抛出异常,没有则返回。
2. 接下来查实现InstantiationAwareBeanPostProcessor的BeanPostProcessor,调⽤实例化之后的后置⽅法。如果返回false,则不会再⾛spring⾃⼰的属性配置。这个应该是留给需要⾃定义装配的。在springboot源码中,我暂时没有看到返回false的BeanPostProcessor。按照我⾃⼰的想法,如果⾃⼰去实现属性的装配,去实现InstantiationAwareBeanPostProcessor就可以了。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论