SpringBoot_Cache源码解析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_26323323/article/details/81774481

前言:

    在上文中,笔者介绍了有关于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依赖

		<dependency>
	        <groupId>org.springframework.boot</groupId>
	        <artifactId>spring-boot-starter-cache</artifactId>
	    </dependency>

    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<String> result = new ArrayList<String>();
        
        // 重点在这里
        // 主要是将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<String> 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.<Integer>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中被添加)

猜你喜欢

转载自blog.csdn.net/qq_26323323/article/details/81774481
今日推荐