Set pieces? Thought it was a novel? Yes, in my opinion code is a novel, every engineer is a novel writer, the general framework is similar and we just have to be appropriate to refine it according to our own ideas.

The objective of the GitHub:https://github.com/pc859107393/Go2SpringBoot.git

Those interested in springboot for rapid development can add the penguin colony below.

Know the Spring cache

Spring Cache technology is similar to other Spring-related technologies we’ve encountered before, in that Spring does not provide an implementation of a real cache, but rather an abstraction for the use of caching. We only need to use the corresponding cache annotation to achieve the cache effect.

Again, this design is very scalable and we can rely on these Settings for integration with Ehcache.

Simple Cache idea

What if we wanted to implement a simple cache? First of all, we do not need to, generally speaking, simply add, delete, change, check and clean up all the cache interface and implementation.

/** * Simple cache interface *@author cheng
 */
interface Cache<T> {
    fun add(key: Any.@Nullable value: T?).

    fun get(key: Any): T?

    fun remove(key: Any)

    fun update(key: Any.@Nullable value: T?).

    fun clear(a)
}

/** * simple cache, when used to initialize the line */
class MapCache<T> : Cache<T> {
    private varhashMap: HashMap<Any, T? > = hashMapOf()override fun add(key: Any, value: T?). {
        hashMap[key] = value
    }

    override fun get(key: Any): T? = hashMap[key]

    override fun update(key: Any, value: T?). {
        hashMap[key] = value
    }

    override fun remove(key: Any) {
        hashMap.remove(key)
    }

    override fun clear(a) {
        hashMap.clear()
    }
}
Copy the code

I believe that the above simple cache processing, we should be able to use, in the method to make a judgment is empty to store or not empty directly out.

But what are the drawbacks of such a cache?

  • Coupling is too high
  • Too invasive
  • Replacing the cache scheme is costly
  • High maintenance costs

Spring’s cache abstraction

In the Spring – the context under the package provides us with the corresponding cache abstraction, complete path for org. Springframework. Cache, we first take a look at this package what below.

  • org.springframework.cache

    • annotation
    • concurrent
    • config
    • interceptor
    • support
    • Cache.java(Cache interface)
    • CacheManager.java(CacheManager interface)

At this point, we can see that concurrent and support may be some concrete implementations of cache. After all, concurrent stands for concurrency and support stands for implementation.

Under the Annotation package, there are Cacheable, CacheConfig, CacheEvict, CachePut, Caching, and EnableCaching, each of which has its own function.

Note the name The main role Using range Refer to the case
EnableCaching Caching the entire bean, which can be used to cache a service Tag a cacheConfig class with the Configuration annotation The @enablecaching annotation for Spring
CacheConfig Provides a set of caching default Settings for all methods of a tagged class The tag is on a class and is often used in the Service layer 1️ cache annotation @cacheable, @cacheput, @cacheevict usage
Cacheable The main function is to cache the results of the method Flags a method and caches the result of that method. Cached on a class that caches the results of all methods under that class 2️ cache annotation @cacheable, @cacheevict, @cacheput usage
CachePut Caching is provided, but the real call is triggered each time and the result is cached. You can synchronize database results to the cache Often used to mark a method and update the result to the cache (or to cache an entire class) 1️ cache annotation @cacheable, @cacheput, @cacheevict usage
CacheEvict More to clear the cache Mark a method to clear the cache under certain conditions (you can also mark a class) 1️ cache annotation @cacheable, @cacheput, @cacheevict usage
Caching Group annotations for multiple cache annotations (different or the same type). Both methods and classes can be tagged Check out the Official Spring documentation

Next we can look at the other resources under the Annotation package, as follows:

  • AbstractCachingConfiguration – > an abstract public cache management functions
/** * provides common cache management functions */
@Configuration
public abstract class AbstractCachingConfiguration implements ImportAware {

	@Nullable
	protected AnnotationAttributes enableCaching;   

	@Nullable
	protected CacheManager cacheManager;    // Cache manager

	@Nullable
	protected CacheResolver cacheResolver;  // Cache resolver

	@Nullable
	protected KeyGenerator keyGenerator;    / / key generator

	@Nullable
	protected CacheErrorHandler errorHandler; / / error Handler


	@Override
	public void setImportMetadata(AnnotationMetadata importMetadata) {// Code omission ···}

	@Autowired(required = false)
	void setConfigurers(Collection<CachingConfigurer> configurers) {// Code omission ···}

	/** * Import CachingConfigurer, unpack it, and assign it to cacheManager, cacheResolver, keyGenerator, and errorHandler */
	protected void useCachingConfigurer(CachingConfigurer config) {// Code omission ···}
}
Copy the code
  • AnnotationCacheOperationSource – > CacheOperationSource interface implementation, used to cache metadata annotations of the tag
/** * An implementation of the CacheOperationSource interface for annotating the cache metadata of the tag. * /
public class AnnotationCacheOperationSource extends AbstractFallbackCacheOperationSource implements Serializable {

	private final boolean publicMethodsOnly; // Whether only public methods are supported

	private final Set<CacheAnnotationParser> annotationParsers; // Annotation parser


	/**
	 * Create a default AnnotationCacheOperationSource, supporting public methods
	 * that carry the {@code Cacheable} and {@codeCacheEvict} annotations. * a default AnnotationCacheOperationSource structure, only support those@Cacheableand@CacheEvictThe public method of the tag. * /
	public AnnotationCacheOperationSource(a) {
		this(true);
	}
    

	@Override
	@Nullable
	protected Collection<CacheOperation> findCacheOperations(finalClass<? > clazz) {
		return determineCacheOperations(parser -> parser.parseCacheAnnotations(clazz));
	}

	@Override
	@Nullable
	protected Collection<CacheOperation> findCacheOperations(final Method method) {
		return determineCacheOperations(parser -> parser.parseCacheAnnotations(method));
	}
	
	// A possible description of the annotation scope for @cacheable and @cacheevict can also be found here in conjunction with the constructor annotations for the two findCacheOperations methods above


	/** * determines the CacheOperation by iterating through the global annotation parser to get the corresponding CacheOperation collection and returning */
	@Nullable
	protected Collection<CacheOperation> determineCacheOperations(CacheOperationProvider provider) {
		Collection<CacheOperation> ops = null;
		for (CacheAnnotationParser annotationParser : this.annotationParsers) {
			Collection<CacheOperation> annOps = provider.getCacheOperations(annotationParser);
			if(annOps ! =null) {
				if (ops == null) {
					ops = newArrayList<>(); } ops.addAll(annOps); }}return ops;
	}
	
	/**
	 * Callback interface providing {@link CacheOperation} instance(s) based on
	 * a given {@link CacheAnnotationParser}.
	 */
	@FunctionalInterface
	protected interface CacheOperationProvider {

		/**
		 * Return the {@link CacheOperation} instance(s) provided by the specified parser.
		 * @param parser the parser to use
		 * @return the cache operations, or {@code null} if none found
		 */
		@Nullable
		Collection<CacheOperation> getCacheOperations(CacheAnnotationParser parser); }}Copy the code
  • The CachingConfigurer interface and CachingConfigurerSupport are implementation classes for the CachingConfigurer interface. CachingConfigurer provides some cache-related inputs: CacheManager, CacheResolver, KeyGenerator, and CacheErrorHandler.

  • CachingConfigurationSelector is CachingConfiguration selector, choose according to configure Proxy or AspectJ.

  • Agent ProxyCachingConfiguration cache management

/ * * * first tag to set up the class, inheritance AbstractCachingConfiguration, states that this is the abstraction cache management implementation * /
@Configuration
public class ProxyCachingConfiguration extends AbstractCachingConfiguration {
    
    // All BeanDefinition.ROLE_INFRASTRUCTURE are background working beans specified within Spring
	@Bean(name = CacheManagementConfigUtils.CACHE_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public BeanFactoryCacheOperationSourceAdvisor cacheAdvisor(a) {
		BeanFactoryCacheOperationSourceAdvisor advisor =
				new BeanFactoryCacheOperationSourceAdvisor();
		advisor.setCacheOperationSource(cacheOperationSource());
		advisor.setAdvice(cacheInterceptor());
		if (this.enableCaching ! =null) {
			advisor.setOrder(this.enableCaching.<Integer>getNumber("order"));
		}
		return advisor;
	}
    
    // It is worth noting that Spring beans are singletons by default, so the method called here is actually the same multiple times
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public CacheOperationSource cacheOperationSource(a) {
		return new AnnotationCacheOperationSource();
	}
    
    // Create a cache interceptor
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public CacheInterceptor cacheInterceptor(a) {
		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);
		}
		returninterceptor; }}Copy the code
  • SpringCacheAnnotationParser Spring’s cache annotation parser
/ / pieces
public class SpringCacheAnnotationParser implements CacheAnnotationParser.Serializable {
    @Override
	@Nullable
	public Collection<CacheOperation> parseCacheAnnotations(Class
        type) {// omit code ··}

	@Override
	@Nullable
	public Collection<CacheOperation> parseCacheAnnotations(Method method) {// omit code ··}

    // The above two parseCacheAnnotations call the following parseCacheAnnotations from the class and method annotations, respectively
    
    // Call parseCacheAnnotations below to implement a specific notation
	@Nullable
	protected Collection<CacheOperation> parseCacheAnnotations(DefaultCacheConfig cachingConfig, AnnotatedElement ae) {
		Collection<CacheOperation> ops = parseCacheAnnotations(cachingConfig, ae, false);
		if(ops ! =null && ops.size() > 1 && ae.getAnnotations().length > 0) {
			// More than one operation found -> local declarations override interface-declared ones...
			Collection<CacheOperation> localOps = parseCacheAnnotations(cachingConfig, ae, true);
			if(localOps ! =null) {
				returnlocalOps; }}return ops;
	}

	@Nullable
	private Collection<CacheOperation> parseCacheAnnotations(
			DefaultCacheConfig cachingConfig, AnnotatedElement ae, boolean localOnly) {
			    // Different operations are implemented depending on the annotation
	}
	
	CacheableOperation parseCacheableAnnotation(AnnotatedElement ae, DefaultCacheConfig defaultConfig, Cacheable cacheable) {
	    // Annotation parsing information assembly for the Cacheable operation
	}
    // There are similar parseEvictAnnotation, parsePutAnnotation, and parseCachingAnnotation methods, which correspond to their own annotation information assembly

    static class DefaultCacheConfig {

		@Nullable
		private final String[] cacheNames;

		@Nullable
		private final String keyGenerator;

		@Nullable
		private final String cacheManager;

		@Nullable
		private final String cacheResolver;
	    
	    // omit the constructor code
	    
	    // Apply the default cache Settings
	    public void applyDefault(CacheOperation.Builder builder) {// omit code ··}}}Copy the code

In the whole org. Springframework. Cache. The annotation under the package, we can see are the notes of caching operations and related resources of parsing and some of the cache Settings. In this case, you can guess the general idea is to generate the corresponding annotation configuration based on the configuration, then scan the annotation and use the annotation configuration specified cache framework to implement caching operations.


So far, the basic annotation package below the things analyzed, in fact, the idea is relatively clear, first look at the annotations, then look at the abstract class and corresponding implementation, and finally consider the interface and implementation of the line.

The real SpringCache is much more than that, and we’ve only seen a glimpse of it.