200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > Spring源码解析-三级缓存与循环依赖 nginx架构图

Spring源码解析-三级缓存与循环依赖 nginx架构图

时间:2020-11-30 10:49:06

相关推荐

Spring源码解析-三级缓存与循环依赖 nginx架构图

两个流程理论上是互不影响的

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)throws BeansException {// bean名称转换// 根据指定的名称获取被管理bean的名称// 如果指定是别名,将别名转换为规范的Bean名称String beanName = transformedBeanName(name);Object bean;​// 从各级缓存中获取bean对象Object sharedInstance = getSingleton(beanName);// 这个判断是跟factoryBean相关的if (sharedInstance != null && args == null) {if (logger.isTraceEnabled()) {if (isSingletonCurrentlyInCreation(beanName)) {logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +"' that is not fully initialized yet - a consequence of a circular reference");}else {logger.trace("Returning cached instance of singleton bean '" + beanName + "'");}}bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}​......​// 创建bean对象if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try {return createBean(beanName, mbd, args);}catch (BeansException ex) {// Explicitly remove instance from singleton cache: It might have been put there// eagerly by the creation process, to allow for circular reference resolution.// Also remove any beans that received a temporary reference to the bean.destroySingleton(beanName);throw ex;}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}​......// 返回bean对象return (T) bean;}

我们重点看两个getSingleton()方法

// 这段代码三级缓存容器都涉及到了,初看有点懵,但是思路不难,先从一级缓存找,找不到去二级缓存找,还找不到去三级缓存// 如果在三级缓存找到了,就放到二级缓存中,非常像数据库跟redis的缓存策略,先到redis中找,找不到去数据库找,找到再写到redis中protected Object getSingleton(String beanName, boolean allowEarlyReference) {// 先从一级缓存中找beanObject singletonObject = this.singletonObjects.get(beanName);// 这里有两个判断,singletonObject == null 表示在一级缓存中找不到bean// isSingletonCurrentlyInCreation()表示该bean是否在创建中// 如果两个条件满足,说明出现了循环依赖if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {synchronized (this.singletonObjects) {// 再从二级缓存中获取singletonObject = this.earlySingletonObjects.get(beanName);// 这里又有两个判断// singletonObject == null 表示在二级缓存中没有获取到// allowEarlyReference 这个值传进来就为true,表示是否允许获取早期引用// 如果两个条件都满足,就到三级缓存中获取if (singletonObject == null && allowEarlyReference) {// 从三级缓存获取,注意,这里获取到是一个ObjectFactoryObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {// 通过ObjectFactory获取bean实例singletonObject = singletonFactory.getObject();// 打怪升级,从三级缓存升级到二级缓存,this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}// 返回beanreturn singletonObject;}

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {

Assert.notNull(beanName, "Bean name must not be null");synchronized (this.singletonObjects) {

// 从一级缓存中获取bean

Object singletonObject = this.singletonObjects.get(beanName);

// 如果bean为空

if (singletonObject == null) {if (this.singletonsCurrentlyInDestruction) {throw new BeanCreationNotAllowedException(beanName,"Singleton bean creation not allowed while singletons of this factory are in destruction " +"(Do not request a bean from a BeanFactory in a destroy method implementation!)");}if (logger.isDebugEnabled()) {logger.debug("Creating shared instance of singleton bean '" + beanName + "'");}

// 单例bean创建前会将这个bean放到一个容器中,标志这个bean正在创建中

beforeSingletonCreation(beanName);boolean newSingleton = false;boolean recordSuppressedExceptions = (this.suppressedExceptions == null);if (recordSuppressedExceptions) {this.suppressedExceptions = new LinkedHashSet<>();}try {

// 执行匿名内部类方法

singletonObject = singletonFactory.getObject();newSingleton = true;}catch (IllegalStateException ex) {singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {throw ex;}}catch (BeanCreationException ex) {if (recordSuppressedExceptions) {for (Exception suppressedException : this.suppressedExceptions) {ex.addRelatedCause(suppressedException);}}throw ex;}finally {if (recordSuppressedExceptions) {this.suppressedExceptions = null;}

// 单例bean创建完成后,会把bean从这个容器中移除

afterSingletonCreation(beanName);}

// newSingleton为true时,表示bean创建成功

if (newSingleton) {

// 把bean放到一级缓存中,一级缓存就是我们常说的IOC容器

addSingleton(beanName, singletonObject);}}return singletonObject;}

}

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没有出现循环依赖时,流程是怎么样的?1. getSingleton()方法查看是否存在于一级缓存中,是则获取,无则走下面的创建流程,因为没有出现循环依赖,isSingletonCurrentlyInCreation(beanName),此判断是false2. createBean()方法创建一个bean3. addSingleton()方法将bean放到一级缓存中当然,在正常的流程中会穿插异常流程的处理方式,比如bean创建前会把bean放到一个容器中,Spring凭借这个可以知道bean是否正在创建中,得知bean在创建中后,会利用三级缓存获得bean空壳```protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {​....​// mbd.isSingleton():bean是否是单例// this.allowCircularReferences:是否允许出现循环依赖// isSingletonCurrentlyInCreation(beanName):bean是否在创建中// 如果三个条件都满足,说明出现了循环依赖boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {if (logger.isTraceEnabled()) {logger.trace("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}// 将bean放到三级缓存中addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}​// Initialize the bean instance.Object exposedObject = bean;try {// 属性赋值populateBean(beanName, mbd, instanceWrapper);// bean初始化exposedObject = initializeBean(beanName, exposedObject, mbd);}catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}}// 如果出现了循环依赖if (earlySingletonExposure) {// 从各级缓存中获取bean,getSingleton(beanName, false)这个方法是不是很熟悉,上面已经使用到了// 只是第二个参数从true变成了false,这个参数决定了要不要从第三级缓存中获取数据// 代码走到这个地方,已经无需获取早期引用了,所以参数为falseObject earlySingletonReference = getSingleton(beanName, false);// 如果二级缓存不为空if (earlySingletonReference != null) {// 并且二级缓存中的bean跟exposedObject相等,说明初始化时,没有使用代理修改bean对象if (exposedObject == bean) {// 直接将二级缓存中bean返回即可exposedObject = earlySingletonReference;}....​return exposedObject;}```我们重点看看addSingletonFactory()这个方法,我们先看一段简单代码,感受一下ObjectFactory这个类的作用```public class ObjectFactoryTest {​​public static void main(String[] args) {HashMap<String, ObjectFactory<?>> map = new HashMap<>(2);map.put("a", () -> {System.out.println("objectFactory");return "string";});​System.out.println(map.get("a").getObject());}}```![image.png](https://img-/img_convert/0a437e603e6bbb7208ac92b516a6703c.png) 原来,ObjectFactory可以定制执行方法,那么Spring要定制的执行方法是什么?```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);}}}

// 要定制的执行方法就是一个beanPostProcess的埋点

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {

Object exposedObject = bean;if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {

最后

送大家一个小福利,点击领取Java全套进阶资料

etons.add(beanName);

}}

}

// 要定制的执行方法就是一个beanPostProcess的埋点protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {Object exposedObject = bean;if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {# 最后**[送大家一个小福利,点击领取Java全套进阶资料](/vip204888/java-p7)**[外链图片转存中...(img-60Y6qU4z-1628591179093)][外链图片转存中...(img-cR7POWt5-1628591179096)]![](https://img-/img_convert/75d03bc41b86865b384048958c2070a0.png)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。