1.启用缓存
- 在springboot中使用@EnableCaching注解开启,导入CachingConfigurationSelector;
- CachingConfigurationSelector根据EnableCaching注解的AdviceMode参数,导入对应的bean;
- 如果是PROXY代理模式,则导入AutoProxyRegistrar、ProxyCachingConfiguration。如果有jsr107的接口定义和具体实现,则额外导入ProxyJCacheConfiguration;
- 如果是ASPECTJ切面模式,则导入AspectJCachingConfiguration。如果有jsr107的接口定义和具体实现,则额外导入AspectJJCacheConfiguration;
- 以上导入的bean,大多是Configuration,各自会又会导入/注册一些该功能依赖的bean;
- 具体过程参见我的另一篇文章:springboot-EnableXX启用配置
2.实际导入的bean
2.1.代理相关的bean
2.1.1.AutoProxyRegistrar
- AutoProxyRegistrar实现ImportBeanDefinitionRegistrar接口,ImportBeanDefinitionRegistrar接口的功能是与@Import一起使用,获取EnableCaching注解中的参数,并注册相关bean。AutoProxyRegistrar使用AopConfigUtils注册自动代理相关的bean;
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//**是否找到EnableCaching注解
boolean candidateFound = false;
//**获取项目中所有的注解类型
Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
for (String annType : annTypes) {
//**获取注解
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
if (candidate == null) {
continue;
}
//**获取注解中的mode参数
Object mode = candidate.get("mode");
//**获取注解中的proxyTargetClass参数
Object proxyTargetClass = candidate.get("proxyTargetClass");
//**mode不为空 && proxyTargetClass不为空 && mode为AdviceMode类型 && proxyTargetClass为Boolean类型
//**满足以上要求的注解为EnableCaching
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
Boolean.class == proxyTargetClass.getClass()) {
//**找到了EnableCaching注解
candidateFound = true;
//**如果为mode为PROXY(Spring动态代理)
if (mode == AdviceMode.PROXY) {
//**注册自动代理相关的bean
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
//**如果启用CGLIB代理
if ((Boolean) proxyTargetClass) {
//**开启CGLIB代理
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
//**找不到EnableCaching注解
if (!candidateFound && logger.isInfoEnabled()) {
String name = getClass().getSimpleName();
...
}
}
}
2.1.2.AopConfigUtils
- AopConfigUtils为Aop工具类,Aop均是使用代理实现的;
- spring代理实现方式:
- 1).jdk动态代理,需要实现接口;
- 2).cglib动态代理,基于继承的方式;
- 3).AspectJ静态代理,AspectJ是静态代理增强,在编译阶段生成AOP代理类。在编译阶段将
Aspect织入Java字节码中;
- AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry),注册了InfrastructureAdvisorAutoProxyCreator,它是基于Advisor匹配机制的自动代理创建器;
- AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry),获取名称为internalAutoProxyCreator的bean定义,添加proxyTargetClass = true,开启CGLIB代理;
- InfrastructureAdvisorAutoProxyCreator如何生成自动代理,下次有机会在深究,不在本篇深究;
//**注册InfrastructureAdvisorAutoProxyCreator
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
//**注册InfrastructureAdvisorAutoProxyCreator
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//**如果已经有名称为internalAutoProxyCreator的bean注册
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
//**获取internalAutoProxyCreator的bean定义
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
//**如果当前internalAutoProxyCreator不是InfrastructureAdvisorAutoProxyCreator类型
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
//**获取当前internalAutoProxyCreator的优先级
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
//**获取InfrastructureAdvisorAutoProxyCreator的优先级
int requiredPriority = findPriorityForClass(cls);
//**如果当前internalAutoProxyCreator的优先级小于InfrastructureAdvisorAutoProxyCreator的优先级,
//**则使用InfrastructureAdvisorAutoProxyCreator替换当前internalAutoProxyCreator
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
//**名称为internalAutoProxyCreator的bean不存在,则注册InfrastructureAdvisorAutoProxyCreator
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
//**获取优先级
private static int findPriorityForClass(Class<?> clazz) {
return APC_PRIORITY_LIST.indexOf(clazz);
}
//**优先级 InfrastructureAdvisorAutoProxyCreator > AspectJAwareAdvisorAutoProxyCreator > AnnotationAwareAspectJAutoProxyCreator
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);
static {
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}
//**获取名称为internalAutoProxyCreator的bean定义,添加proxyTargetClass = true,开启CGLIB代理
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
2.2.缓存相关的bean
2.2.1.ProxyCachingConfiguration
- 它是一个@Configuration,导入的3个bean,
- BeanFactoryCacheOperationSourceAdvisor:基于cache操作的Advisor,在spring切面(pointcut)判断是否拦截(是否有缓存注解),并调用CacheInterceptor;
- AnnotationCacheOperationSource:缓存注解解析,把Cacheable、CachePut和CacheEvict注解解析为相应的缓存操作(CacheOperation);
- CacheInterceptor:实现MethodInterceptor接口,aop的方法拦截器,缓存代理类会调用此方法进行相应的缓存处理;
- 它继承自AbstractCachingConfiguration;
- AbstractCachingConfiguration实现了ImportAware,获取EnableCaching注解;
- 注入了CachingConfigurer,如果有自定义了CachingConfigurer实现,可获取到此配置项;
@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyCachingConfiguration extends AbstractCachingConfiguration {
//**注册BeanFactoryCacheOperationSourceAdvisor,名称为internalCacheAdvisor
@Bean(name = CacheManagementConfigUtils.CACHE_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryCacheOperationSourceAdvisor cacheAdvisor() {
BeanFactoryCacheOperationSourceAdvisor advisor = new BeanFactoryCacheOperationSourceAdvisor();
advisor.setCacheOperationSource(cacheOperationSource());
advisor.setAdvice(cacheInterceptor());
if (this.enableCaching != null) {
advisor.setOrder(this.enableCaching.<Integer>getNumber("order"));
}
return advisor;
}
//**注册AnnotationCacheOperationSource
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public CacheOperationSource cacheOperationSource() {
return new AnnotationCacheOperationSource();
}
//**注册CacheInterceptor
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public CacheInterceptor cacheInterceptor() {
CacheInterceptor interceptor = new CacheInterceptor();
interceptor.configure(this.errorHandler, this.keyGenerator, this.cacheResolver, this.cacheManager);
interceptor.setCacheOperationSource(cacheOperationSource());
return interceptor;
}
}
@Configuration
public abstract class AbstractCachingConfiguration implements ImportAware {
//**获取EnableCaching注解
@Override
public void setImportMetadata(AnnotationMetadata importMetadata) {
this.enableCaching = AnnotationAttributes.fromMap(importMetadata.getAnnotationAttributes(EnableCaching.class.getName(), false));
...
}
//**获取自定义CachingConfigurer配置
@Autowired(required = false)
void setConfigurers(Collection<CachingConfigurer> configurers) {
if (CollectionUtils.isEmpty(configurers)) {
return;
}
//**CachingConfigurer配置只能有一个
if (configurers.size() > 1) {
throw new IllegalStateException(...);
}
CachingConfigurer configurer = configurers.iterator().next();
useCachingConfigurer(configurer);
}
//**如果自定义了CachingConfigurer配置,则使用自定义CachingConfigurer的配置
protected void useCachingConfigurer(CachingConfigurer config) {
this.cacheManager = config::cacheManager;
this.cacheResolver = config::cacheResolver;
this.keyGenerator = config::keyGenerator;
this.errorHandler = config::errorHandler;
}
}
2.3.其它
- 本人测试的时候并没用jsr107的接口定义和具体实现,没有深究ProxyJCacheConfiguration、AspectJCachingConfiguration和AspectJJCacheConfiguration,下次有机会在深究;