spring源码10: spring从缓存中获取bean

	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

		/**
		 * 1. 转换beanName,存在一下2种情况
		 * 		1.当获取的是工厂而非bean时,beanName会带上&,此时需要先去掉&
		 * 		2.如果是别名,将别名转化为真实的beanName
 		 */
		final String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
		// 2. 尝试从缓存中获取bean
		Object sharedInstance = getSingleton(beanName);
		
		// 这节我们只关心第二点,因此后面先暂时注释掉
		...
	}

1. 转换为真实beanName(先回顾一下)

由于传入的beanName可能带&前缀需要获取工厂,也有可能是别名。因此需要做以下转换,找出真实的beanName

	protected String transformedBeanName(String name) {
		// 先调用transformedBeanName去除前缀,再调用canonicalName替换别名
		return canonicalName(BeanFactoryUtils.transformedBeanName(name));
	}

	// 去除前缀
	public static String transformedBeanName(String name) {
		Assert.notNull(name, "'name' must not be null");
		// FACTORY_BEAN_PREFIX = "&",不包含&前缀直接返回
		if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
			return name;
		}
		return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
			do {
				// 去除FACTORY_BEAN_PREFIX前缀,知道不包含前缀
				beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
			}
			while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
			return beanName;
		});
	}

	// 替换别名
	public String canonicalName(String name) {
		String canonicalName = name;
		// Handle aliasing...
		String resolvedName;
		do {
			// 通过aliasMap获取beanName,直到不再有别名
			resolvedName = this.aliasMap.get(canonicalName);
			// 可能存在A->B->C->D,所以需要一直循环直到没有别名位置
			if (resolvedName != null) {
				canonicalName = resolvedName;
			}
		}
		while (resolvedName != null);
		return canonicalName;
	}

2. 从缓存中获取bean

// AbstractBeanFactory.java
// 2. 尝试从缓存中获取bean
Object sharedInstance = getSingleton(beanName);

这里我将缓存分为三级:

  • singletonObject:一级缓存,该缓存key = beanName, value = bean;这里的bean是已经创建完成的,该bean经历过实例化->属性填充->初始化以及各类的后置处理。因此,一旦需要获取bean时,我们第一时间就会寻找一级缓存

  • earlySingletonObjects:二级缓存,该缓存key = beanName, value = bean;这里跟一级缓存的区别在于,该缓存所获取到的bean是提前曝光出来的,是还没创建完成的。也就是说获取到的bean只能确保已经进行了实例化,但是属性填充跟初始化肯定还没有做完,因此该bean还没创建完成,仅仅能作为指针提前曝光,被其他bean所引用

  • singletonFactories:三级缓存,该缓存key = beanName, value = beanFactory;在bean实例化完之后,属性填充以及初始化之前,如果允许提前曝光,spring会将实例化后的bean提前曝光,也就是把该bean转换成beanFactory并加入到三级缓存。在需要引用提前曝光对象时再通过singletonFactory.getObject()获取

  • registeredSingletons:保存着所有注册过单例的beanName,是一个set确保不重复

// DefaultSingletonBeanRegistry.java
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// 从一级缓存获取,key=beanName value=bean
		Object singletonObject = this.singletonObjects.get(beanName);
		// singletonObject为空,且该bean正在创建中(假设不在创建中那么肯定是还没被实例化以及提前曝光的,继续查找没有意义)
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				// 从二级缓存获取,key=beanName value=bean
				singletonObject = this.earlySingletonObjects.get(beanName);
				// 是否允许循环引用
				if (singletonObject == null && allowEarlyReference) {
					// 从缓存中获取BeanFactory
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						// 通过getObject()方法获取bean,获取到的实例不单单是提前曝光出来的实例,它还经过了SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference方法处理过。这也正是三级缓存存在的意义,用户可以通过重写该后置处理器对提前曝光的实例进行一些操作
						singletonObject = singletonFactory.getObject();
						// 将三级缓存生产的bean放入二级缓存中
						this.earlySingletonObjects.put(beanName, singletonObject);
						// 删除三级缓存
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

拓展:三级缓存相关方法

为了让大家对三级缓存有更深的理解,我们看看三级缓存都是怎么被使用的

  1. addSingleton:添加单例缓存,当bean被创建完以后进行的操作。这时候说明bean已经创建完,删除二三级缓存,直接留下一级缓存,并且注册该bean
	protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
			// bean创建完毕,删除二三级缓存,留下以一级缓存。
			this.singletonObjects.put(beanName, singletonObject);
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			// 注册当前beanName
			this.registeredSingletons.add(beanName);
		}
	}
  1. addSingletonFactory:添加单例工厂缓存,也就是添加三级缓存
	protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		synchronized (this.singletonObjects) {
			// 只有一级缓存不存在的情况下,才会尝试缓存singletonFactory(三级缓存)
			if (!this.singletonObjects.containsKey(beanName)) {
				this.singletonFactories.put(beanName, singletonFactory);
				this.earlySingletonObjects.remove(beanName);
				this.registeredSingletons.add(beanName);
			}
		}
	}
  1. removeSingleton:移出单例,则全部缓存一起清空
	protected void removeSingleton(String beanName) {
		synchronized (this.singletonObjects) {
			this.singletonObjects.remove(beanName);
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.remove(beanName);
		}
	}
  1. containsSingleton:查询bean是否在一级缓存中
	public boolean containsSingleton(String beanName) {
		return this.singletonObjects.containsKey(beanName);
	}
  1. clearSingletonCache:清空缓存,则把所有的缓存都clear掉,请勿混淆clear跟remove
	protected void clearSingletonCache() {
		synchronized (this.singletonObjects) {
			this.singletonObjects.clear();
			this.singletonFactories.clear();
			this.earlySingletonObjects.clear();
			this.registeredSingletons.clear();
			this.singletonsCurrentlyInDestruction = false;
		}
	}
发布了30 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/chaitoudaren/article/details/104833545
今日推荐