Spring 三级缓存 源码分析 测试代码如下:
启动类
1 2 3 4 5 6 7 @SpringBootApplication public class TestApplication { public static void main (String[] args) { ConfigurableApplicationContext configurableApplicationContext = SpringApplication.run(TradeApplication.class, args); configurableApplicationContext.getBean("testClassA" ); } }
TestClassA
1 2 3 4 5 6 7 8 @Lazy @Component public class TestClassA { @Transactional(rollbackFor = Exception.class) public void test () { System.out.println("testA" ); } }
TestClassB
1 2 3 4 5 6 7 @Lazy @Component public class TestClassB { @Resource private TestClassA testClassA; }
这里都加上 @Lazy
的原因是 springboot 原本启动时还会加载其他的内部的 bean,为了更好的测试分析,让 TestClassA 和 TestClassB 延迟加载,再通过 getBean 方法在第一次获取 TestClassA 对应的 bean 的时候再加载
通过 configurableApplicationContext.getBean("testClassA")
的 getBean 一路调试进去,会来到 AbstractBeanFactory.doGetBean
这个方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 protected <T> T doGetBean ( String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null ) { beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null ); } else { if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } }); beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } } return adaptBeanInstance(name, beanInstance, requiredType); }
从关注点 1 Object sharedInstance = getSingleton(beanName)
进入到 DefaultSingletonBeanRegistry.getSingleton
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 private final Map<String, Object> singletonObjects = new ConcurrentHashMap <>(256 );private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap <>(16 );private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap <>(16 );public Object getSingleton (String beanName) { return getSingleton(beanName, true ); } protected Object getSingleton (String beanName, boolean allowEarlyReference) { Object singletonObject = this .singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { singletonObject = this .earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { synchronized (this .singletonObjects) { singletonObject = this .singletonObjects.get(beanName); if (singletonObject == null ) { singletonObject = this .earlySingletonObjects.get(beanName); if (singletonObject == null ) { ObjectFactory<?> singletonFactory = this .singletonFactories.get(beanName); if (singletonFactory != null ) { singletonObject = singletonFactory.getObject(); this .earlySingletonObjects.put(beanName, singletonObject); this .singletonFactories.remove(beanName); } } } } } } return singletonObject; }
DefaultSingletonBeanRegistry.isSingletonCurrentlyInCreation
的逻辑如下
1 2 3 public boolean isSingletonCurrentlyInCreation (String beanName) { return this .singletonsCurrentlyInCreation.contains(beanName); }
判断一级缓存中是否存在该 bean,如果存在直接返回,如果不存在走第 2 步
判断二级缓存中是否存在该 bean 并且isSingletonCurrentlyInCreation(beanName)
返回是否为 true(判断当前 bean 是否正在被创建),不满足条件返回 null
但是因为testClassA
这个 bean 现在还没被创建,并且isSingletonCurrentlyInCreation(beanName)
这个方法返回的是 false(为什么是 false 后面会提到),所以直接返回 null
因为上面找不到所以会跑到关注点 2,这里也是调用 DefaultSingletonBeanRegistry.getSingleton
方法,但是实现的逻辑和上面的不同
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public Object getSingleton (String beanName, ObjectFactory<?> singletonFactory) { synchronized (this .singletonObjects) { Object singletonObject = this .singletonObjects.get(beanName); if (singletonObject == null ) { beforeSingletonCreation(beanName); boolean newSingleton = false ; try { singletonObject = singletonFactory.getObject(); newSingleton = true ; } finally { afterSingletonCreation(beanName); } if (newSingleton) { addSingleton(beanName, singletonObject); } } return singletonObject; } }
DefaultSingletonBeanRegistry.beforeSingletonCreation
逻辑如下
1 2 3 4 5 protected void beforeSingletonCreation (String beanName) { if (!this .inCreationCheckExclusions.contains(beanName) && !this .singletonsCurrentlyInCreation.add(beanName)) { throw new BeanCurrentlyInCreationException (beanName); } }
主要关注点 4 中的逻辑主要是将 beanName 加入到 singletonsCurrentlyInCreation 中(singletonsCurrentlyInCreation 是个 Set 集合,只有不存在的时候才可以将 beanName 添加进去),而 singletonsCurrentlyInCreation 就在前面 DefaultSingletonBeanRegistry.isSingletonCurrentlyInCreation
被用到,所以前面为什么返回的 false
前面还有this.inCreationCheckExclusions.contains(beanName)
这个判断,从名字能猜到 inCreationCheckExclusions 里面存放的是那些不需要被检查是否正在创建中的 beanName,如果不需要被检查就不需要添加到 singletonsCurrentlyInCreation 中
关注点 5 singletonFactory.getObject()
是个 lambda 表达式,真正的逻辑其实就是关注点 3 中的createBean(beanName, mbd, args)
,最终会调用到 AbstractAutowireCapableBeanFactory.doCreateBean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 protected Object doCreateBean (String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { BeanWrapper instanceWrapper = null ; if (mbd.isSingleton()) { instanceWrapper = this .factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null ) { instanceWrapper = createBeanInstance(beanName, mbd, args); } Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } boolean earlySingletonExposure = (mbd.isSingleton() && this .allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); } if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false ); if (earlySingletonReference != null ) { if (exposedObject == bean) { 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); } } } } } }
关注点 8 主要是对实例化一个 bean,没什么好说的,关注点 9 判断的就是 bean 是否是单例(mbd.isSingleton()
)并且允许循环依赖(this.allowCircularReferences
)并且 bean 正在被创建(isSingletonCurrentlyInCreation(beanName)
,前面介绍过了),earlySingletonExposure 在这里为 true(前面两个条件一般情况下都是 true ,第三个条件根据前面的介绍也是为 true)
DefaultSingletonBeanRegistry.addSingletonFactory
逻辑如下
1 2 3 4 5 6 7 8 9 10 11 protected void addSingletonFactory (String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(singletonFactory, "Singleton factory must not be null" ); synchronized (this .singletonObjects) { if (!this .singletonObjects.containsKey(beanName)) { this .singletonFactories.put(beanName, singletonFactory); this .earlySingletonObjects.remove(beanName); this .registeredSingletons.add(beanName); } } }
earlySingletonExposure 为 true 说明 bean 可以提早暴露,addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean))
就是将 bean 先放入三级缓存,不过留意到这里加入三级缓存的是一个 ObjectFactory (先记住后面会提到)
关注点 10 主要是初始化 bean,populateBean(beanName, mbd, instanceWrapper)
依赖注入,exposedObject = initializeBean(beanName, exposedObject, mbd)
初始化 bean ,在这个测试例子中 TestClassA 需要注入 TestClassB,尝试从缓存获取 TestClassB 对应的 bean,但是因为 TestClassB 对应的 bean 还未被创建,所以和 TestClassA 创建 bean 的过程一样创建 TestClassB 的 bean,按照前面的逻辑走到 populateBean(beanName, mbd, instanceWrapper)
这一步,发现 TestClassB 中需要依赖 TestClassA,这个时候就从缓存中获取 TestClassA 的 bean,就是关注点 1 中的Object sharedInstance = getSingleton(beanName)
(留意 allowEarlyReference 为 true 才会从三级缓存中获取),在三级缓存中获取到 TestClassA 的 ObjectFactory,通过 singletonObject = singletonFactory.getObject()
获取到 TestClassA 的 bean,之后通过this.earlySingletonObjects.put(beanName, singletonObject)
和 this.singletonFactories.remove(beanName)
这两段代码将 TestClassA bean 放入到二级缓存,将 TestClassA 的 ObjectFactory 从三级缓存中移除
从上面的分析可以知道singletonObject = singletonFactory.getObject()
这段获取 TestClassA 的 bean 其实调用的就是AbstractAutowireCapableBeanFactory.getEarlyBeanReference
这个方法
1 2 3 4 5 6 7 8 9 protected Object getEarlyBeanReference (String beanName, RootBeanDefinition mbd, Object bean) { Object exposedObject = bean; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) { exposedObject = bp.getEarlyBeanReference(exposedObject, beanName); } } return exposedObject; }
SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference
逻辑如下
1 2 3 4 5 public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor { default Object getEarlyBeanReference (Object bean, String beanName) throws BeansException { return bean; } }
AbstractAutoProxyCreator.getEarlyBeanReference
逻辑如下
1 2 3 4 5 6 7 8 9 public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor , BeanFactoryAware { @Override public Object getEarlyBeanReference (Object bean, String beanName) { Object cacheKey = getCacheKey(bean.getClass(), beanName); this .earlyProxyReferences.put(cacheKey, bean); return wrapIfNecessary(bean, beanName, cacheKey); } }
SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference
返回的就是传进去的 bean,但是 AbstractAutoProxyCreator 重写了 getEarlyBeanReference ,它其实就是 Spring 的代理实现,返回 bean 的代理对象,传入的 bean 被存放在代理对象的 target 成员变量中(如果不懂的话可以去了解一下代理模式,了解一下静态代理和动态代理是如何实现的),我们这里 TestClassA 上用到声明式事务(@Transactional 注解),所以这里 TestClassA 对应的 bean 不能返回原来的 bean,而是被 AbstractAutoProxyCreator 处理后的代理对象(后面都以 ProxyTestClassA 命名代理类),最后将 ProxyTestClassA 的 bean 注入到 TestClassB 的 bean 中,到此 TestClassB 的 bean 基本已经初始化完成,之后就是回到关注点 6 和关注点 7
afterSingletonCreation(beanName)
逻辑如下
1 2 3 4 5 protected void afterSingletonCreation (String beanName) { if (!this .inCreationCheckExclusions.contains(beanName) && !this .singletonsCurrentlyInCreation.remove(beanName) { throw new IllegalStateException ("Singleton '" + beanName + "' isn't currently in creation" ); } }
因为 TestClassB 的 bean 已经完成实例化和初始化,所以将 TestClassB 的 beanName 从标记正在创建中的 singletonsCurrentlyInCreation 集合中移除
addSingleton(beanName, singletonObject)
的逻辑如下
1 2 3 4 5 6 7 8 9 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); } }
addSingleton(beanName, singletonObject)
就是将 TestClassB 的 bean 放入一级缓存,并且将 bean 从二级和三级缓存中移除
之后就是回到关注点 10 的 TestClassA 的 bean 初始化(注意 TestClassA 的 bean 其实还初始化完成,前面说的一堆实例化和初始化 TestClassB 的 bean 逻辑都是因为 TestClassA 的 bean 需要注入 TestClassB 的 bean 导致的),将 TestClassB 的 bean 注入 TestClassA 的 bean 中,这个对于 TestClasA 的 bean 的处理基本完成,但是和 TestClassB 的创建和初始化有点不同的是在关注点 11
关注点 11 的Object earlySingletonReference = getSingleton(beanName, false)
(这里传入的 allowEarlyReference 就是为 false 最多只会从二级缓存获取),前面二级缓存中存入了 TestClassA 的代理类 ProxyTestClassA 的 bean,所以通过 beanName 获取到的就是 ProxyTestClassA 的 bean,所以最后返回就是 earlySingletonReference(指向 ProxyTestClassA 的 bean 并且里面 target 指向的被代理 TestClassA 的 bean 已经初始化完成),之后的逻辑就和 TestClassB 的一样了
是否一定要使用三级缓存