ProxyCachingConfiguration
其实这个哥们的设计思想和ProxyTransactionManagementConfiguration
如出一辙,只是各自处理各自的业务属性不同而已。
// @since 3.1 内部注入的Bean角色都是ROLE_INFRASTRUCTURE 建议先看下面的父类 @Configuration @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public class ProxyCachingConfiguration extends AbstractCachingConfiguration { // 缓存注解的增强器:重点在CacheOperationSource和CacheInterceptor @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; } // 关于CacheOperationSource和CacheInterceptor是理解注解原理重要的两个类,放在下一章节讲解更妥 // 注意CacheOperationSource是给CacheInterceptor用的 @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public CacheOperationSource cacheOperationSource() { return new AnnotationCacheOperationSource(); } @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; } } // 抽象父类:定义和管理了Caching相关的API、类们 @Configuration public abstract class AbstractCachingConfiguration implements ImportAware { // 这些属性都是protected的,子类可以直接访问哦~~~ @Nullable protected AnnotationAttributes enableCaching; @Nullable protected Supplier<CacheManager> cacheManager; @Nullable protected Supplier<CacheResolver> cacheResolver; // 缓存注解的处理器 @Nullable protected Supplier<KeyGenerator> keyGenerator; // key的生成器 @Nullable protected Supplier<CacheErrorHandler> errorHandler; // 错误处理器 // 继承此抽象类前提条件:必须标注@EnableCaching注解~ @Override public void setImportMetadata(AnnotationMetadata importMetadata) { this.enableCaching = AnnotationAttributes.fromMap(importMetadata.getAnnotationAttributes(EnableCaching.class.getName(), false)); if (this.enableCaching == null) { throw new IllegalArgumentException("@EnableCaching is not present on importing class " + importMetadata.getClassName()); } } // 可以通过实现CachingConfigurer接口来**指定缓存使用的默认**的: // 缓存管理器 // 缓存解析器 // key生成器 // 错误处理器 @Autowired(required = false) void setConfigurers(Collection<CachingConfigurer> configurers) { if (CollectionUtils.isEmpty(configurers)) { return; } // CachingConfigurer的实现类,最多只能有一个 if (configurers.size() > 1) { throw new IllegalStateException(configurers.size() + " implementations of " + "CachingConfigurer were found when only 1 was expected. " + "Refactor the configuration such that CachingConfigurer is " + "implemented only once or not at all."); } CachingConfigurer configurer = configurers.iterator().next(); useCachingConfigurer(configurer); } /** * Extract the configuration from the nominated {@link CachingConfigurer}. */ protected void useCachingConfigurer(CachingConfigurer config) { this.cacheManager = config::cacheManager; this.cacheResolver = config::cacheResolver; this.keyGenerator = config::keyGenerator; this.errorHandler = config::errorHandler; } }
可以看到@EnableCaching这个注解的模式和@EnableTransactionManagement的效果是何其相似,所以掌握模式往往比掌握具体某一种技术更重要~
上面配置类向容器放入的三个Bean:BeanFactoryCacheOperationSourceAdvisor、CacheOperationSource、CacheInterceptor它是AOP处理缓存注解的核心,这在下一章节有详细的解释说明~
总结
本文先介绍了@EnableCaching它开启缓存注解支持的基本原理,从本文更应该得到的一个道理是:掌握模式往往比掌握具体的一门技术更加重要,这也就是战略和战术的区别吧~