用Tinkercad Codeblocks可视化编程,从零设计3D打印卡祖笛
2026/6/2 22:52:00
Spring 三级缓存主要解决两个核心问题:
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { // 第一级缓存:完全初始化好的单例Bean private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); // 第二级缓存:提前暴露的单例Bean(已实例化但未完成初始化) private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16); // 第三级缓存:单例工厂(用于创建Bean的早期引用,可能包含代理对象) private final Map<String, ObjectFactory<?>> singletonFactories = new ConcurrentHashMap<>(16); // 正在创建中的Bean名称集合 private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16)); // 已注册的单例Bean名称集合 private final Set<String> registeredSingletons = new LinkedHashSet<>(256); }一级缓存存储完全初始化完成的 Bean 实例
特点:
二级缓存存储提前暴露的 Bean 实例(已实例化但未完成属性注入)
特点:
三级缓存存储ObjectFactory 工厂对象,用于创建 Bean 的早期引用
特点:
ObjectFactory<?>而不是 Bean 实例getObject()方法可以创建 Bean 的早期引用addSingletonFactory():添加三级缓存将创建 Bean 的工厂放入三级缓存,为循环依赖提供出口
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) { synchronized (this.singletonObjects) { if (!this.singletonObjects.containsKey(beanName)) { // 放入三级缓存 this.singletonFactories.put(beanName, singletonFactory); // 从二级缓存移除(保证数据一致性) this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } }4.2 getSingleton():获取单例Bean涉及所有三级缓存:按 1→2→3 顺序查找
三级缓存的查询逻辑:
protected Object getSingleton(String beanName, boolean allowEarlyReference) { // 快速检查一级缓存(完全初始化的Bean) Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { // 检查二级缓存(提前暴露的Bean) singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { // 检查三级缓存(Bean工厂) ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { // 调用工厂方法获取Bean的早期引用 singletonObject = singletonFactory.getObject(); // 将获取到的Bean放入二级缓存 this.earlySingletonObjects.put(beanName, singletonObject); // 从三级缓存移除 this.singletonFactories.remove(beanName); } } } } return singletonObject; }4.3 getEarlyBeanReference():获取早期Bean引用从三级缓存 获取工厂时调用,生成早期引用(可能是代理对象)
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { Object exposedObject = bean; // 如果BeanDefinition不是合成的(非基础设施Bean)且存在InstantiationAwareBeanPostProcessor if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; // 关键:后置处理器可能返回代理对象 exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName); } } } return exposedObject; }假设有两个Service,且A需要AOP代理:
@Service @Transactional // A需要事务代理 public class ServiceA { @Autowired private ServiceB serviceB; public void methodA() { // 业务逻辑 } } @Service public class ServiceB { @Autowired private ServiceA serviceA; public void methodB() { // 业务逻辑 } }详细执行流程:
构造器调用时对象还未创建,无法放入三级缓存,因此无法解决循环依赖。
@Component public class ServiceA { private final ServiceB serviceB; @Autowired // 构造器注入 public ServiceA(ServiceB serviceB) { this.serviceB = serviceB; // 构造时就依赖B,但B可能还未创建 // 此时ServiceA还未实例化完成,ServiceA 无法放入三级缓存 } }原型Bean不放入三级缓存,每次请求都创建新实例
@Scope("prototype") @Component public class PrototypeA { @Autowired private PrototypeB b; } @Scope("prototype") @Component public class PrototypeB { @Autowired private PrototypeA a; }Spring会直接抛出异常:BeanCurrentlyInCreationException: Error creating bean with name 'prototypeA': Requested bean is currently in creation
@Async也是通过AOP实现的,但处理时机不同;
需要在initializeBean阶段创建代理,可能影响循环依赖
@Service public class AsyncService { @Async public void asyncMethod() { // 异步方法 } @Autowired private AnotherService anotherService; }| 缓存级别 | 存储内容 | 生命周期 | 主要作用 |
|---|---|---|---|
| 一级缓存 | 完全初始化的Bean | Bean整个生命周期 | 提供最终可用的Bean |
| 二级缓存 | 早期Bean(已实例化未初始化) | 创建过程中临时存在 | 解决循环依赖,避免重复创建 |
| 三级缓存 | ObjectFactory工厂对象 | Bean实例化后到初始化前 | 处理AOP代理,确保返回正确的代理对象 |
核心思想:通过懒加载的ObjectFactory延迟决策,只有在真正发生循环依赖时才创建代理对象,既解决了循环依赖问题,又保持了Bean生命周期的完整性,同时支持AOP等增强功能。