前言:
在上文中,笔者介绍了有关于SpringCache的使用及源码解析
读者可先了解下这篇文章 https://blog.csdn.net/qq_26323323/article/details/81746265
了解下其源码分析过程,这样有助于本文的源码分析
实际在现在的很多项目中,SpringBoot+ 已经成为一种主流了,SpringBoot+组件的使用极大的方便了我们队相关组件的使用。
但就其原理而言,实际没有特别高深的东西,只是把原来的很多Spring+组件的方式用SpringBoot的方式写了一遍而已,我们在使用的过程中直接引用其SpringBoot注解即可了。
下面我们就来看下其源码解析
1.SpringBoot_Cache的使用
具体使用过程,笔者不再赘述,网上有很多关于其用法的文章,读者可自行查看。
也可参考: https://www.jianshu.com/p/fc076b6c2a13 这篇关于其用法还是比较全面的
其主要过程可分为:
1)添加maven依赖
org.springframework.boot
spring-boot-starter-cache
2)在Application类上添加注解
@EnableCaching
public class SpringbootstudyApplication {}
3)使用@Cache
@Cacheable(cacheNames = "test")
public String get(String id) {}
2.写在源码分析之前
我们通过对SpringCache的源码分析可知,主要是通过xml配置将以下四个类注入到Spring容器中
* InfrastructureAdvisorAutoProxyCreator(实现BeanPostProcessor接口)
* AnnotationCacheOperationSource
* CacheInterceptor(主要的拦截功能都实现在这里)
* BeanFactoryCacheOperationSourceAdvisor(重点关注这个,这个类在创建代理的时候被使用)
最终功能都是通过这四个类来实现的,那么对SpringBoot_Cache的源码过程,我们也要围绕着四个类看分析,通过分析其源码,找到这四个类的创建以及如何注入到Spring容器中
3.@EnableCaching注解分析
通过SpringBoot_Cache的使用过程分析可知,其主要就是一句注解@EnableCaching,主要功能应该都在这里面实现的,我们来看下这个注解
1)@EnableCaching
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(CachingConfigurationSelector.class)// 重点在这里
public @interface EnableCaching {}
可见其将类CachingConfigurationSelector注入Spring中
2)CachingConfigurationSelector分析
通过对其代码结构的分析,可知其实现了ImportSelector接口,那么就会实现其selectImports()方法,在这个方法里会注入类到Spring中,我们来看下这个方法
// AdviceModeImportSelector.selectImports()
public final String[] selectImports(AnnotationMetadata importingClassMetadata) {
// 1.获取@EnableCaching注解
Class> annoType = GenericTypeResolver.resolveTypeArgument(getClass(), AdviceModeImportSelector.class);
// 2.获取@EnableCaching注解的详细信息{order=2147483647, mode=PROXY, proxyTargetClass=false}
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
if (attributes == null) {
throw new IllegalArgumentException(String.format(
"@%s is not present on importing class '%s' as expected",
annoType.getSimpleName(), importingClassMetadata.getClassName()));
}
// 3.mode默认为PROXY
AdviceMode adviceMode = attributes.getEnum(this.getAdviceModeAttributeName());
// 4.调用父类实现
String[] imports = selectImports(adviceMode);
if (imports == null) {
throw new IllegalArgumentException(String.format("Unknown AdviceMode: '%s'", adviceMode));
}
return imports;
}
// CachingConfigurationSelector.selectImports()
public String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
// 默认执行该方法
return getProxyImports();
case ASPECTJ:
return getAspectJImports();
default:
return null;
}
}
// CachingConfigurationSelector.getProxyImports()
private String[] getProxyImports() {
List result = new ArrayList();
// 重点在这里
// 主要是将AutoProxyRegistrar和ProxyCachingConfiguration两个类注入到Spring中
result.add(AutoProxyRegistrar.class.getName());
result.add(ProxyCachingConfiguration.class.getName());
if (jsr107Present && jcacheImplPresent) {
result.add(PROXY_JCACHE_CONFIGURATION_CLASS);
}
return result.toArray(new String[result.size()]);
}
总结:通过对@EnableCaching注解的分析,可知其最终是将两个类注入到Spring中
* AutoProxyRegistrar
* ProxyCachingConfiguration
下面我们来分析下这两个类的作用
3.AutoProxyRegistrar分析
源码如下:
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
// 1.获取Application类上的注解,也就是@EnableCaching注解
Set annoTypes = importingClassMetadata.getAnnotationTypes();
for (String annoType : annoTypes) {
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
if (candidate == null) {
continue;
}
Object mode = candidate.get("mode");// 默认为PROXY
Object proxyTargetClass = candidate.get("proxyTargetClass");
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
if (mode == AdviceMode.PROXY) {
// 重点是这句
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
...
}
}
// AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAutoProxyCreatorIfNecessary(registry, null);
}
// registerAutoProxyCreatorIfNecessary()
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
总结:又看到了熟悉的面孔,InfrastructureAdvisorAutoProxyCreator类被注入进来
4.ProxyCachingConfiguration源码分析
@Configuration
public class ProxyCachingConfiguration extends AbstractCachingConfiguration {
// 1.创建BeanFactoryCacheOperationSourceAdvisor bean
// 名称为org.springframework.cache.config.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());
advisor.setOrder(this.enableCaching.getNumber("order"));
return advisor;
}
// 2.创建AnnotationCacheOperationSource bean
// 名称为cacheOperationSource
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public CacheOperationSource cacheOperationSource() {
return new AnnotationCacheOperationSource();
}
// 3.创建CacheInterceptor bean
// 名称为cacheInterceptor
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public CacheInterceptor cacheInterceptor() {
CacheInterceptor interceptor = new CacheInterceptor();
interceptor.setCacheOperationSources(cacheOperationSource());
if (this.cacheResolver != null) {
interceptor.setCacheResolver(this.cacheResolver);
}
else if (this.cacheManager != null) {
interceptor.setCacheManager(this.cacheManager);
}
if (this.keyGenerator != null) {
interceptor.setKeyGenerator(this.keyGenerator);
}
if (this.errorHandler != null) {
interceptor.setErrorHandler(this.errorHandler);
}
return interceptor;
}
总结:很明显的看出来,当前类创建了三个bean
* BeanFactoryCacheOperationSourceAdvisor
* CacheOperationSource
* CacheInterceptor
总结:
通过以上代码的分析可知,通过注解@EnableCaching的使用,总共注入了四个类到Spring中,也就是我们在SpringCache中的那四个类
* InfrastructureAdvisorAutoProxyCreator(在AutoProxyRegistrar中被添加)
* BeanFactoryCacheOperationSourceAdvisor(在ProxyCachingConfiguration中被添加)
* CacheOperationSource(在ProxyCachingConfiguration中被添加)
* CacheInterceptor(在ProxyCachingConfiguration中被添加)