三级缓存的实现原理是:
1.在创建 bean 实例时,将正在创建的 bean 放入一个“当前正在创建的 bean”集合中。
2.当 bean 实例化完成后,将其放入一个“已经创建好的 bean”集合中。
3.当需要使用到该 bean 时,先从“当前正在创建的 bean”集合中查找是否存在该 bean,如果存在则说明出现了循环依赖,抛出异常;否则从“已经创建好的 bean”集合中查找是否存在该 bean,如果存在则返回该 bean,否则创建 bean 并放入“已经创建好的 bean”集合中。
在 Spring Boot 中,可以通过自定义 BeanPostProcessor 来实现三级缓存。具体步骤如下:
1.创建一个类,实现 BeanPostProcessor 接口,并重写 postProcessBeforeInitialization 和 postProcessAfterInitialization 方法。
2.在 postProcessBeforeInitialization 方法中,将正在创建的 bean 放入“当前正在创建的 bean”集合中。
3.在 postProcessAfterInitialization 方法中,将已经创建好的 bean 放入“已经创建好的 bean”集合中。
4.在需要使用到该 bean 的地方,通过 ApplicationContext.getBean() 方法获取该 bean,自动触发 BeanPostProcessor 的 postProcessBeforeInitialization 和 postProcessAfterInitialization 方法,从而实现三级缓存。
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
private Map<String, Object> singletonObjects = new ConcurrentHashMap<>(); // 已经创建好的 bean 集合
private Set<String> singletonCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>()); // 当前正在创建的 bean 集合
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (singletonCurrentlyInCreation.contains(beanName)) { // 如果当前正在创建的 bean 集合中包含该 bean,则说明出现了循环依赖,抛出异常
throw new BeanCurrentlyInCreationException(beanName);
}
singletonCurrentlyInCreation.add(beanName); // 将该 bean 放入“当前正在创建的 bean”集合中
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
singletonCurrentlyInCreation.remove(beanName); // 将该 bean 从“当前正在创建的 bean”集合中移除
singletonObjects.put(beanName, bean); // 将该 bean 放入“已经创建好的 bean”集合中
return bean;
}
public Object getSingleton(String beanName) {
return singletonObjects.get(beanName);
}
}
在需要使用到该 bean 的地方,可以通过以下方式获取:
CustomBeanPostProcessor customBeanPostProcessor = applicationContext.getBean(CustomBeanPostProcessor.class);
Object bean = customBeanPostProcessor.getSingleton(beanName);
if (bean == null) {
bean = applicationContext.getBean(beanName);
}