一、String類及常用方法 String :字元串,使用一對""引起來表示。 1.理解String的不可變性 (1)String實現了Serializable介面:表示字元串是支持序列化的 (2)實現了Comparable介面:可以比較大小 (3)String內部定義了final char[] v ...
結構包:
使用案例:
實現效果:
1、基本併發的本地緩存,基於分散式輕量級鎖的redis緩存
2、熱緩存(高頻訪問持續緩存)+快速過期(本地緩存2秒,redis緩存10秒)
3、方法級別緩存清理 (@HybridCache 與@HybridChange 綁定管理緩存 )
4、基於HybridType介面的可擴展式作用域,目前已實現:全局、token
5、基於HybridLevel介面的可擴展式緩存處理,目前已實現:本地緩存、redis緩存
核心代碼包:
package com.*.server.live.core.hybridCache; import com.*.server.live.core.hybridCache.impl.DepthLocal; import com.*.server.live.core.hybridCache.impl.DepthRedis; import java.lang.annotation.*; /** * 功能描述:多重緩存 * 作者:唐澤齊 * @case @HybridCache(scope = ScopeGlobal.class) */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface HybridCache { /*緩存深度*/ Class<? extends HybridLevel> depth() default DepthRedis.class; /*緩存廣度*/ Class<? extends HybridType> scope(); }@HybridCache
package com.*.server.live.core.hybridCache; import com.*.server.live.core.hybridCache.impl.DepthRedis; import java.lang.annotation.*; /** * 功能描述:多重緩存更新 * 作者:唐澤齊 * @case @HybridChange(clazz = LiveStudioController.class,method = "getStudio",args = {Long.class}) * @case @HybridChange(clazz = LiveStudioController.class,method = "getStudio",args = {}) */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface HybridChange { /*關聯類*/ Class<? extends Object> clazz(); /*關聯方法*/ String method(); /*關聯方法入參類型*/ Class<?>[] args(); }@HybridChange
package com.*.server.live.core.hybridCache; import org.aspectj.lang.ProceedingJoinPoint; import javax.validation.constraints.NotNull; /** * 功能描述:多重緩存級別 * 作者:唐澤齊 */ public interface HybridLevel { /** * 緩存 * @param key 緩存key * @param id 混村ID * @param o 緩存值 * @param self 是否執行節點 * @param joinPoint 節點 * @return * @throws Throwable */ Object cache(@NotNull String key,@NotNull String id, Object o,@NotNull boolean self,@NotNull ProceedingJoinPoint joinPoint) throws Throwable; /** * 清緩存 * @param key 緩存key * @param self 是否執行節點 * @param joinPoint 節點 * @return * @throws Throwable */ Object del(@NotNull String key,@NotNull boolean self,@NotNull ProceedingJoinPoint joinPoint) throws Throwable; }HybridLevel
package com.*.server.live.core.hybridCache; /** * 功能描述:多重緩存級別 * 作者:唐澤齊 */ public interface HybridType { String token(); }HybridType
package com.*.server.live.core.hybridCache; import com.alibaba.fastjson.JSON; import com.alibaba.nacos.common.util.Md5Utils; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Configuration; import javax.annotation.Resource; import java.lang.reflect.Method; /** * 功能描述:多重緩存介面 * 作者:唐澤齊 */ @Aspect @Configuration public class HybridCacheInterceptor { @Resource ApplicationContext applicationContext; final static String cache = "hybridCache:"; @Around(value = "@annotation(com.*.server.live.core.hybridCache.HybridCache)") public Object cache(ProceedingJoinPoint joinPoint) throws Throwable { MethodSignature ms = (MethodSignature) joinPoint.getSignature(); Method method = ms.getMethod(); HybridCache cacheAnnotation = method.getAnnotation(HybridCache.class); String key = getCacheKey(method); String id = getCacheId(method,joinPoint.getArgs()); HybridLevel hybridLevel = applicationContext.getBean(cacheAnnotation.depth()); return hybridLevel.cache(key, id, null, true, joinPoint); } @Around(value = "@annotation(com.*.server.live.core.hybridCache.HybridChange)") public Object del(ProceedingJoinPoint joinPoint) throws Throwable { MethodSignature ms = (MethodSignature) joinPoint.getSignature(); Method method = ms.getMethod(); HybridChange cacheAnnotation = method.getAnnotation(HybridChange.class); try { Method method1 = cacheAnnotation.clazz().getMethod(cacheAnnotation.method(),cacheAnnotation.args()); HybridCache cache = method1.getAnnotation(HybridCache.class); String key = getCacheKey(method1); HybridLevel hybridLevel = applicationContext.getBean(cache.depth()); return hybridLevel.del(key,true, joinPoint); } catch (Exception e) { return joinPoint.proceed(); } } /*獲取緩存key*/ private String getCacheKey(Method method) { return cache + method.getDeclaringClass().getSimpleName() + ":" + method.getName(); } ; /*獲取緩存id*/ private String getCacheId(Method method,Object[] args) { HybridCache cacheAnnotation = method.getAnnotation(HybridCache.class); HybridType hybridType = applicationContext.getBean(cacheAnnotation.scope()); return Md5Utils.getMD5((hybridType.token() + JSON.toJSONString(args)).getBytes()); } ; }HybridCacheInterceptor
擴展代碼包:
package com.*.server.live.core.hybridCache.impl; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.*.server.live.core.hybridCache.HybridLevel; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import java.util.concurrent.TimeUnit; /** * 功能描述:本地緩存 * 作者:唐澤齊 */ @Component public class DepthLocal implements HybridLevel { /*自帶讀寫鎖*/ public volatile static Cache<String, Object> localCache = CacheBuilder.newBuilder().initialCapacity(144).expireAfterAccess(2, TimeUnit.SECONDS).build(); @Override public Object cache(String key, String id, Object o, boolean search, ProceedingJoinPoint joinPoint) throws Throwable { String keyId = key + ":" + id; MethodSignature ms = (MethodSignature) joinPoint.getSignature(); if (search && o == null && (o = localCache.getIfPresent(keyId)) == null) { synchronized (ms.getMethod()) { if ((o = localCache.getIfPresent(keyId)) == null) { o = joinPoint.proceed(); localCache.put(keyId, o); } } } if (o == null) { o = localCache.getIfPresent(keyId); } else { localCache.put(keyId, o); } return o; } @Override public Object del(String key, boolean self, ProceedingJoinPoint joinPoint) throws Throwable { Object o = null; if (self) { o = joinPoint.proceed(); } localCache.cleanUp(); return o; } }DepthLocal
package com.*.server.live.core.hybridCache.impl; import cn.hutool.core.util.RandomUtil; import com.*.common.redis.service.RedisService; import com.*.server.live.core.hybridCache.HybridLevel; import org.aspectj.lang.ProceedingJoinPoint; import org.springframework.stereotype.Component; import javax.annotation.Resource; /** * 功能描述:redis緩存 * 作者:唐澤齊 */ @Component public class DepthRedis implements HybridLevel { @Resource private RedisService redisService; @Resource private HybridLevel depthLocal; @Override public synchronized Object cache(String key, String id, Object o,boolean search, ProceedingJoinPoint joinPoint) throws Throwable { o = depthLocal.cache(key, id, o,false,joinPoint); String lock = getLock(key, id); if(search && o== null && (o=redisService.hget(key , id)) == null ) { for (;;) { if(redisService.incr(lock,1l) <= 1l && (o=redisService.hget(key , id)) == null ) { try { o = joinPoint.proceed(); redisService.hset(key , id, o, 10l); } catch (Throwable e) { throw e; }finally { redisService.del(lock); } } else { o = redisService.hget(key , id); } if(o == null) { Thread.sleep(1); } else { break; } } } if (o == null) { o = redisService.hget(key , id); } else { depthLocal.cache(key, id, o,false,joinPoint); redisService.hset(key , id, o, 10l); } return o; } @Override public Object del(String key,boolean self, ProceedingJoinPoint joinPoint) throws Throwable { Object o = null; if (self) { o = joinPoint.proceed(); } redisService.del(key); depthLocal.del(key,false,joinPoint); return o; } private String getLock(String key, String id) { return this.getClass().getSimpleName()+":"+key+":"+id; } }DepthRedis
package com.*.server.live.core.hybridCache.impl; import com.*.server.live.core.hybridCache.HybridType; import org.springframework.stereotype.Component; /** * 功能描述:全局級別 * 作者:唐澤齊 */ @Component public class ScopeGlobal implements HybridType { @Override public String token() { return ""; } }ScopeGlobal
package com.*.server.live.core.hybridCache.impl; import com.*.common.core.utils.*Util; import com.*.server.live.core.hybridCache.HybridType; import org.springframework.stereotype.Component; /** * 功能描述:token級別 * 作者:唐澤齊 */ @Component public class ScopeToken implements HybridType { @Override public String token() { return *Util.getCurrentTokenValue(); } }ScopeToken