Spring的三级缓存

参考:https://blog.csdn.net/weixin_36380516/article/details/113904400

一、aop使用

注解类 TimeLog
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TimeLog {

    String invokename() default "";

    String prefix() default "";
}
LogAspect 切面类
@Component
@Aspect
public class LogAspect {

    @Before("@annotation(TimeLog)")
    public void logBefore() {
        System.out.println("logBefore ~~~~~");
    }


    @After("@annotation(TimeLog)")
    public void logAfter() {
        System.out.println("logAfter ~~~~~");
    }

}
AopController 目标类
@Controller
public class AopController {

    @TimeLog(invokename = "AopController.requestTest", prefix = "requestTest")
    public void requestTest() {
        System.out.println("requestTest 启动~~");
    }
}
AopControllerTest 测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class AopControllerTest {

    @Test
    public void test() {
        ApplicationContext applicationContext = ApplicationContextHolder.getContext();
        AopController aopController = (AopController) applicationContext.getBean("aopController");

    }
}

二、三级缓存验证

1、有AOP,无循环依赖

项目初始化时,创建单例bean

AbstractBeanFactory#doGetBean

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

   final String beanName = transformedBeanName(name);
   Object bean;

   // Eagerly check singleton cache for manually registered singletons.
   Object sharedInstance = getSingleton(beanName);
   //--------
    
         // Create bean instance.
         if (mbd.isSingleton()) {
            // 获取单例bean
            sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
               @Override
               public Object getObject() throws BeansException {
                  try {
                     //创建Bean
                     return createBean(beanName, mbd, args);
                  }
                   -----
               }
            });
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
         }

    
   return (T) bean;
}

获取单例bean,并缓存到一级缓存singletonObjects,删除三级缓存中的bean

DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "'beanName' must not be null");
    synchronized (this.singletonObjects) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
            if (this.singletonsCurrentlyInDestruction) {
                throw new BeanCreationNotAllowedException(beanName,
                                                          "Singleton bean creation not allowed while the 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 + "'");
            }
            beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet<Exception>();
            }
            try {
                //回调 createBean 方法
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            }
            
            if (newSingleton) {
                // 添加单例Bean到一级缓存 singletonObjects
                addSingleton(beanName, singletonObject);
            }
        }
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }
}

单例bean实例化、依赖注入和初始化(内部aop增强),并缓存到三级缓存 singletonFactories

AbstractAutowireCapableBeanFactory#doCreateBean

//真正创建Bean的方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) {

    // Instantiate the bean.
    //封装被创建的Bean对象
    BeanWrapper instanceWrapper = null;
  
    //---1--- 实例化Bean
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    
   
    //向容器中缓存单例模式的Bean对象,以防循环引用
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                                      isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        // **************** 缓存到  singletonFactories三级缓存中
        //这里是一个匿名内部类,为了防止循环引用,尽早持有对象的引用.  缓存到  singletonFactories三级缓存中
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    //Bean对象的初始化,依赖注入在此触发
    //这个exposedObject在初始化完成之后返回作为依赖注入完成后的Bean
    Object exposedObject = bean;
    try {
        //---2--- 依赖注入
        //将Bean实例对象封装,并且Bean定义中配置的属性值赋值给实例对象
        populateBean(beanName, mbd, instanceWrapper);
        //---3--- 初始化bean
        //初始化Bean对象,并aop增强
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    return exposedObject;
}

这里三级缓存没有任何用处,初始完成后三级缓存中观察的bean缓存情况如下:

一级缓存 singletonObjects: 缓存 aopController

二级缓存 earlySingletonObjects: 未缓存 aopController

三级缓存 singletonFactories: 缓存 aopController,缓存到一级缓存后删除

2、无aop,有循环依赖

这里

3、有aop,有循环依赖

AService、BService aop增强并循环依赖。

这里先创建AService对象,依赖注入时需要getBean(“bService”),接着创建BService对象,依赖注入时需要获取 AService对象,通过三级缓存获取AService对象,代码如下:

AbstractBeanFactory#doGetBean

//真正实现向IOC容器获取Bean的功能,也是触发依赖注入功能的地方
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
                          @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

    //根据指定的名称获取被管理Bean的名称,剥离指定名称中对容器的相关依赖
    //如果指定的是别名,将别名转换为规范的Bean名称
    final String beanName = transformedBeanName(name);
    Object bean;

    // Eagerly check singleton cache for manually registered singletons.
    //先从缓存中取是否已经有被创建过的单态类型的Bean
    //对于单例模式的Bean整个IOC容器中只创建一次,不需要重复创建; 比如循环依赖注入时,从缓存中获取bean
    Object sharedInstance = getSingleton(beanName);
    //IOC容器创建单例模式Bean实例对象
    if (sharedInstance != null && args == null) {
        ……
    }
    ……
}

调用 getSingleton 代码获取AService对象实例

DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)

@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            // 从二级缓存中获取对象,
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    // 为何对象从三级缓存中删除,放入二级缓存中呢?   aop 一般是类初始化后增加的,aop循环依赖则是在下面代理增强的。
                    // 解决多个aop类循环依赖,放入二级缓存, 后面初始化此类时,查询到已经有代理过的对象,就不会创建代理对象了,保证代理类的唯一
                    singletonObject = singletonFactory.getObject(); // singletonObject 为代理的实例 beanproxy
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return singletonObject;
}

singletonFactory.getObject() 这里调用匿名内部类方法 getEarlyBeanReference

注意源码 创建Bean时,代码:addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); 这里是匿名内部类调用的方法getEarlyBeanREference()

如下,如果被代理增强,返回bean的代理对象

AbstractAutowireCapableBeanFactory#getEarlyBeanReference

//如果bean被代理返回bean的代理对象,如果未被代理,返回bean实例对象
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
   Object exposedObject = bean;
   if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
         if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
            SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
            exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
         }
      }
   }
   return exposedObject;
}

一级缓存 singletonObjects:最终缓存了AService代理对象和BService代理对象

二级缓存 earlySingletonObjects: 中间缓存了AService提前生成的代理对象,解决代理循环依赖的问题; 这里如果有个CService,如下图, 二级缓存就有存在的必要了。

三级缓存 singletonFactories:缓存了bean的工厂类

img

结论

1、没有依赖,有AOP 这种情况中,我们知道 AOP 代理对象的生成是在成品对象创建完成之后创建的,这也是 Spring 的设计原则,代理对象尽量推迟创建。

代理对象为何尽量推迟创建?

2、循环依赖 + AOP 这种情况中, AService 代理对象的生成提前了,因为必须要保证其 AOP 功能,但 BService 代理对象的生成还是遵循的 Spring 的原则。

3、三级缓存各自的作用

第一级缓存存的是对外暴露的对象,也就是我们应用需要用到的

第二级缓存的作用是为了处理循环依赖的对象创建问题,里面存的是半成品对象或半成品对象的代理对象

第三级缓存的作用处理存在 AOP + 循环依赖的对象创建问题,能将代理对象提前创建

三、Spring 为什么要引入第三级缓存

严格来讲,第三级缓存并非缺它不可,因为可以提前创建代理对象

提前创建代理对象只是会节省那么一丢丢内存空间,并不会带来性能上的提升,但是会破环 Spring 的设计原则

Spring 的设计原则是尽可能保证普通对象创建完成之后,再生成其 AOP 代理(尽可能延迟代理对象的生成)

所以 Spring 用了第三级缓存,既维持了设计原则,又处理了循环依赖;牺牲那么一丢丢内存空间是愿意接受的。

四、为何要尽可能延迟代理对象的生成

Spring有自己的设计原则,职责尽量分得细,代理对象的创建尽量放在后面。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值