1. 目标
实现4种自定注解:
- InstantCache,作用于方法,缓存方法的返回结果,1秒内有效。
- ShortCache,作用于方法,缓存方法的返回结果,方法超过10秒没有被调用,上次缓存的结果就失效。
- ModerateCache,作用于方法,缓存方法的返回结果,方法超过2分钟没有被调用,上次的结果就失效。
- LongCache,作用于方法,缓存方法的返回结果,10分钟内有效。
2. 实现
2.1 配置
- pom.xml
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
<version>2.4.4</version>
</dependency>
- application.properties
#cache
spring.cache.type=jcache
spring.cache.jcache.provider=org.ehcache.jsr107.EhcacheCachingProvider
spring.cache.jcache.config=classpath:/ehcache.xml
2.2 注解定义
- InstantCache
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Cacheable(cacheNames = "instantCache" , keyGenerator = "com.cimstech.ms.common.cache.MethodKeyGen")
public @interface InstantCache {
}
- ShortCache
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Cacheable(cacheNames = "shortCache" , keyGenerator = "com.cimstech.ms.common.cache.MethodKeyGen")
public @interface ShortCache {
}
- ModerateCache
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Cacheable(cacheNames = "moderateCache" , keyGenerator = "com.cimstech.ms.common.cache.MethodKeyGen")
public @interface ModerateCache {
}
- LongCache
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Cacheable(cacheNames = "longCache" , keyGenerator = "com.cimstech.ms.common.cache.MethodKeyGen")
public @interface LongCache {
}
- EnableCache
@Documented
@Retention(RUNTIME)
@Target({ TYPE })
@Import(MethodKeyGen.class)
@EnableCaching
public @interface EnableCache
{
}
2.3 MethodKeyGen实现
@Component
public class MethodKeyGen implements KeyGenerator
{
public MethodKeyGen()
{
}
@Override
public Object generate(Object aTarget, Method aMethod, Object... aParams)
{
String objId = getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(aTarget)) ;
# XString.toString()用来拼接参数,每个参数转成String,用“()”包裹,然后用“,”连接
return objId +"."+aMethod.getName()+XString.toString(",", "(", ")", aParams) ;
}
}
2.4 ehcache.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:jsr107='http://www.ehcache.org/v3/jsr107' xmlns='http://www.ehcache.org/v3'
xsi:schemaLocation="http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.1.xsd
http://www.ehcache.org/v3/jsr107 http://www.ehcache.org/schema/ehcache-107-ext-3.1.xsd">
<!-- 距离加入缓存开始超过1秒,就从缓存中清楚 -->
<cache alias="instantCache">
<key-type>java.lang.String</key-type>
<value-type>java.lang.Object</value-type>
<expiry>
<ttl unit="seconds">1</ttl>
</expiry>
<heap unit="entries">2000</heap>
</cache>
<!-- 距上次取用超过10秒,将从缓存中清除 -->
<cache alias="shortCache">
<key-type>java.lang.String</key-type>
<value-type>java.lang.Object</value-type>
<expiry>
<tti unit="seconds">10</tti>
</expiry>
<heap unit="entries">1000</heap>
</cache>
<!-- 距上次取用超过2分钟,将从缓存中清除 -->
<cache alias="moderateCache">
<key-type>java.lang.String</key-type>
<value-type>java.lang.Object</value-type>
<expiry>
<tti unit="minutes">2</tti>
</expiry>
<heap unit="entries">2000</heap>
</cache>
<!-- 距对象加入缓存开始超过10分钟,将从缓存中清除 -->
<cache alias="longCache">
<key-type>java.lang.String</key-type>
<value-type>java.lang.Object</value-type>
<expiry>
<ttl unit="minutes">10</ttl>
</expiry>
<heap unit="entries">2000</heap>
</cache>
</config>
3. 使用方法
- MainApplication上加上@EnableCache
@EnableCache
@SpringBootApplication
public class MainApplication
{
...省略更多
}
- 在需要缓存的地方上加上期望的缓存注解
@Component
public class TaskServerSite
{
@InstantCache
public JSONArray getTasksOfType(String aName , TaskType aTaskType)
{
...省略代码
}
}
需要注意,SpringCache的内部实现是基于AOP的,这是一种代理技术,意味着同一个对象的方法间相互调用,缓存是不会起作用的。如果原先不是很理解AOP技术,可以这样类比理解,AOP代理相当于网关,不同对象间相互调用,相当于不同服务经过网关相互调用,网关就可以帮忙做缓存,而同一个对象的方法间相互调用,相当于服务自己调自己的接口,是不经过网关的,网关上的缓存就不会起作用。
网友评论