Spring三级缓存、循环依赖、AOP
1. 简介
三级缓存:
缓存 | 属性 | 说明 |
---|---|---|
一级缓存 | singletonObjects | 保存初始化的单例Bean |
二级缓存 | earlySingletonObjects | 保存实例化、未初始化的单例Bean |
三级缓存 | singletonFactories | 保存实例化的单例Bean |
循环依赖:两个Bean互相依赖的场景
2. 流程
入口
@EnableAspectJAutoProxy
,作用:@Import(AspectJAutoProxyRegistrar.class)
@Import(AspectJAutoProxyRegistrar.class)
,作用:向IoC容器注册自动代理创建器BeanDefinition
自动代理创建器
优先级从低到高:
-
InfrastructureAdvisorAutoProxyCreator
-
AspectJAwareAdvisorAutoProxyCreator
-
AnnotationAwareAspectJAutoProxyCreator
作用:属于Bean后置处理器,或是早期暴露、或是后置处理时创建代理
创建代理流程
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
-
获取所有增强器
-
找出canApply的增强器
-
排序
-
创建代理
@Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
3. 三级缓存与早期暴露
场景:现有两个Bean(A、B),先进行A的创建,后进行B的创建
AB都不是代理
-
A:实例化、属性填充
-
B:实例化、属性填充
- 触发
getEarlyBeanReference
获取A的早期引用 - A进入二级缓存
- B继续剩余属性填充、初始化
- B进入一级缓存
- 触发
-
A继续剩余属性填充、初始化
-
A进入一级缓存
B是代理
-
A:实例化、属性填充
-
B:实例化、属性填充
- 触发
getEarlyBeanReference
获取A的早期引用 - A进入二级缓存
- B继续剩余属性填充、初始化创建代理(后置处理时生成)
- B进入一级缓存
- 触发
-
A继续剩余属性填充、初始化
-
A进入一级缓存
A是代理
-
A:实例化、属性填充
-
B:实例化、属性填充
- 触发
getEarlyBeanReference
获取A的早期引用,生成代理(早期暴露时生成) - A代理进入二级缓存
- B继续剩余属性填充、初始化
- B进入一级缓存
- 触发
-
A继续剩余属性填充、初始化
-
A早期暴露回调:使用二级缓存的代理,替换被代理对象A
-
A进入一级缓存
AB都是代理
-
A:实例化、属性填充
-
B:实例化、属性填充
- 触发
getEarlyBeanReference
获取A的早期引用,生成代理(早期暴露时生成) - A进入二级缓存
- B继续剩余属性填充、初始化,生成代理(后置处理时生成)
- B进入一级缓存
- 触发
-
A继续剩余属性填充、初始化(后置处理,创建代理前提条件不满足,直接返回。原因:earlyProxyReferences存在)
-
A早期暴露回调:使用二级缓存的代理,替换被代理对象A
-
A进入一级缓存