spring 中的“三级缓存”

spring中的三级缓存

  • 一级缓存:singletonObject  存放已经经历了完整周期的Bean对象
  • 二级缓存:earlySingletonObjects 存放早期暴露出来的Bean对象,Bean的生命周期未结束
  • 三级缓存:singletonFactories 存放可以生成Bean的工厂

 三个Map有什么异同

缓存其实就是三个Map

  • 一级缓存:它是spring容器,存放完整的Bean实例,已经实例化和初始化好的实例
  • 二级缓存:bean不管是否被AOP切面代理,“否”代表保存半成品的Bean实例,属性未填充,“是”代表,保存代理的实例BeanProxy,Bean还是半成品
  • 三级缓存:存放的是ObjectFactory,传入的是一个匿名内部类,ObjectFactory.getObject()最终调用的是getEarlyBeanReference方法

 什么是循环依赖

循环依赖:就是 N 个类循环(嵌套)使用。就是多个 Bean 之间互相依赖或引用到对方,最终形成了 闭环

spring的三级缓存是为了解决对象间的循环依赖问题。

A依赖B,B依赖A,这就是一个简单的循环依赖。

查看spring三级缓存的源码

查看路径

package org.springframework.beans.factory.support;

四个关键的方法

getSingleton(),doCreatBean(),populateBean(),addSingleton()

1.获取Bean的源码
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    //一级缓存
    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);
    //已经注册的单例池里的beanName
    private final Set<String> registeredSingletons = new LinkedHashSet(256);
    //正在创建中的beanName集合
    private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap(16));
    @Nullable //缓存查找bean  如果第1级缓存没有,那么从第2级缓存获取。如果第2级缓存也没有,那么从第3级缓存创建,并放入第2级缓存
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && this.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) {
                             //第3级缓存  在doCreateBean中创建了bean的实例后,封装ObjectFactory放入缓存的bean实例
                            ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                            if (singletonFactory != null) {
                                //创建未赋值的Bean
                                singletonObject = singletonFactory.getObject();
                                //存放到二级缓存中 
                                this.earlySingletonObjects.put(beanName, singletonObject);               //从三级缓存中删除
                                this.singletonFactories.remove(beanName);
                            }
                        }
                    }
                }
            }
        }

        return singletonObject;
    }
}
2.“添加到第1级缓存”的源码:
 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);
        }
    }
3.“添加到第3级缓存”的源码:
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);
            }

        }
    }
4.创建Bean的源码:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// 1. 从factoryBeanInstanceCache缓存中尝试获取
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		// 2. 如果缓存中不存在,则根据bean对应的策略创建新的实例,如:工厂方法、构造器自动注入、简单初始化
		if (instanceWrapper == null) {
			// Bean对象实例化
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch ...
				mbd.postProcessed = true;
			}
		}
		// 3.是否需要提前曝光 = 单例&允许循环依赖&bean正在创建中
		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));
		}

		// 4. 对bean属性进行填充,注入bean中的属性
		Object exposedObject = bean;
		try {
			//填充属性
			populateBean(beanName, mbd, instanceWrapper);
			//bean对象初始化
			//调用初始化方法,比如init-method、注入Aware对象、应用后处理器
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
	    catch····
        return exposedObject;

	}

对于三级缓存解决循环依赖的问题

我们只能使用field 属性注入(setter方法注入)循环依赖

为什么不能使用 构造器注入循环依赖来解决

Spring 解决循环依赖依靠的是 Bean " 中间态 " 这个概念,而这个中间态指的是已经实例化但还没初始化的状态 —>半成品。实例化的过程又是通过构造器创建的,如果 A 还没创建好出来怎么可能提前曝光,所以构造器的循环依赖无法解决
由于 spring 中的 bean 的创建过程为先实例化 再初始化 ( 在进行对象实例化的过程中不必赋值 ) 将实例化好的对象暴露出去, 供其他对象调用 , 然而使用构造器注入 , 必须要使用构造器完成对象的初始化的操作 ,就会陷入死循环的状态

一级缓存能不能解决循环依赖问题

不能,因为在三个级别的缓存中存储的对象是有区别的 一级缓存为完全实例化且初始化的对象 二级缓存实例化但未初始化对象,Bean对象还是一个半成品 如果只有一级缓存,如果是并发操作下,就有可能取到实例化但未初始化的对象,就会出现问题

二级缓存能不能解决循环依赖问题?

理论上二级缓存可以解决循环依赖问题 , 但是需要注意——>
为什么需要在三级缓存中存储匿名内部类 (ObjectFactory)

原因在于"需要创建代理对象 eg:现有A,需要生成代理对象 A ,需要进行实例化" 

在三级缓存中:存放的是ObjectFactory,传入的是一个匿名内部类,ObjectFactory.getObject()最终调用的是getEarlyBeanReference方法,该类可能是代理类也可能是普通的对象,而使用三级缓存可以保证 无论是否需要是代理对象,都可以保证使用的是同一个对象,而不会出现,一会儿使用普通 bean 一会儿使用代理类

### Spring 框架中的三级缓存机制 在Spring框架中,缓存配置提供了三层定制级别来控制缓存行为。这些层次分别为全局级、类级以及操作级。 #### 全局级缓存配置 全局级缓存配置通过`CacheManager``KeyGenerator`实现,适用于整个应用程序范围内的默认设置[^2]。此级别的配置影响所有未特别指定其他策略的地方。 ```java @Configuration @EnableCaching public class CacheConfig { @Bean public CacheManager cacheManager() { SimpleCacheManager cacheManager = new SimpleCacheManager(); List<Cache> caches = Arrays.asList( new ConcurrentMapCache("default"), // 可以添加更多默认缓存实例... ); cacheManager.setCaches(caches); return cacheManager; } } ``` #### 类级缓存配置 (@CacheConfig) 类级缓存配置允许开发者针对特定控制器或服务组件应用统一的缓存参数。此类别下的方法共享相同的前缀或其他公共属性[^1]。 ```java @RestController @RequestMapping("/api/cache") @CacheConfig(cacheNames = "users") // 设置该controller下所有cacheable的方法都使用名为"users"的缓存区域 public class UserController { @GetMapping("/{id}") @Cacheable(value = "userDetails", key = "#id") public User getUser(@PathVariable String id) { // 方法逻辑... } } ``` #### 操作级缓存配置 最具体的层是单个缓存操作上的配置,它能够覆盖更广泛的设定并提供细粒度控制。这意味着即使存在更高层次的定义,在具体的操作上也可以有不同的表现形式。 ```java @Service public class UserService { @CachePut(value = "users", key = "#result.id") public User updateUser(User user){ // 更新用户的业务逻辑... return userRepository.save(user); } @CacheEvict(value = "users", allEntries=true) public void clearUserCache(){ // 清除用户缓存的具体实现... } } ``` 这种分层结构使得开发人员可以根据需求灵活调整不同部分的行为而不会相互干扰,同时也简化了维护工作量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值