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.