6.springboot cache启用

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,下次有机会在深究;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值