最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

關于spring的自定義緩存注解分析

 更新時間:2023年05月12日 09:56:58   作者:morris131  
這篇文章主要介紹了關于spring的自定義緩存注解分析,因為所有的key的失效時間都一樣,要想實現(xiàn)不同的key不同的失效時間,就得需要自定義緩存注解,需要的朋友可以參考下

為什么要自定義緩存注解?

Spring Cache本身提供@Cacheable、@CacheEvict、@CachePut等緩存注解,為什么還要自定義緩存注解呢?

@Cacheabe不能設置緩存時間,導致生成的緩存始終在redis中,當然這一點可以通過修改RedisCacheManager的配置來設置緩存時間:

@Bean
public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
	RedisCacheConfiguration redisCacheConfiguration = getRedisCacheConfiguration();
	RedisCacheManager cacheManager = RedisCacheManager
			.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
			.cacheDefaults(redisCacheConfiguration)
			.build();
	return cacheManager;
}
private RedisCacheConfiguration getRedisCacheConfiguration() {
	Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
	ObjectMapper om = new ObjectMapper();
	om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
	om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
	jackson2JsonRedisSerializer.setObjectMapper(om);
	RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
	redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(
			RedisSerializationContext
					.SerializationPair
					.fromSerializer(jackson2JsonRedisSerializer)
	).entryTtl(Duration.ofDays(7)); // 設置全局key的有效事件為7天
	return redisCacheConfiguration;
}

不過這個設置時全局的,所有的key的失效時間都一樣,要想實現(xiàn)不同的key不同的失效時間,還得自定義緩存注解。

自定義緩存注解

Cached

類似Spring Cache的@Cacheable。

package com.morris.spring.custom.cache.annotation;
import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.*;
import java.util.concurrent.TimeUnit;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Cached {
	@AliasFor("cacheName")
	String value() default "";
	@AliasFor("value")
	String cacheName() default "";
	int expire() default 0;
	TimeUnit expireUnit() default TimeUnit.SECONDS;
	String key();
	String condition() default "";
	String unless() default "";
	boolean sync() default false;
}

CacheUpdate

類似于Spring Cache的@CachePut。

package com.morris.spring.custom.cache.annotation;
import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.*;
import java.util.concurrent.TimeUnit;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface CacheUpdate {
	@AliasFor("cacheName")
	String value() default "";
	@AliasFor("value")
	String cacheName() default "";
	int expire() default 0;
	TimeUnit expireUnit() default TimeUnit.SECONDS;
	String key();
	String condition() default "";
	String unless() default "";
}

CacheInvalidate

類似于Spring Cache的@CacheEvict。

package com.morris.spring.custom.cache.annotation;
import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface CacheInvalidate {
	@AliasFor("cacheName")
	String value() default "";
	@AliasFor("value")
	String cacheName() default "";
	String key();
	String condition() default "";
	String unless() default "";
}

CachedAspect

@Cached注解的切面實現(xiàn)。

package com.morris.spring.custom.cache.annotation;
import com.morris.spring.custom.cache.Level2Cache;
import com.morris.spring.custom.cache.Level2CacheManage;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.cache.Cache;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.expression.EvaluationContext;
import javax.annotation.Resource;
import java.util.Objects;
@Configuration
@Aspect
@EnableAspectJAutoProxy // 開啟AOP
public class CachedAspect {
	@Resource
	private Level2CacheManage cacheManager;
	@Around(value = "@annotation(cached)")
	public Object around(ProceedingJoinPoint joinPoint, Cached cached) throws Throwable {
		Level2Cache cache = cacheManager.getCache(cached.cacheName());
		ExpressionEvaluator evaluator = new ExpressionEvaluator();
		EvaluationContext context = evaluator.createEvaluationContext(joinPoint);
		Object key = evaluator.key(cached.key(), context);
		if(cached.sync()) {
			//
			return cache.get(key, () -> {
				try {
					return joinPoint.proceed();
				} catch (Throwable e) {
					e.printStackTrace();
					return null;
				}
			});
		}
		// 先查緩存
		Cache.ValueWrapper valueWrapper = cache.get(key);
		if (Objects.nonNull(valueWrapper)) {
			return valueWrapper.get();
		}
		Object result = joinPoint.proceed();
		context.setVariable("result", result);
		Boolean condition = evaluator.condition(cached.condition(), context);
		Boolean unless = evaluator.unless(cached.unless(), context);
		if (condition && !unless) {
			if (cached.expire() > 0) {
				cache.put(key, result, cached.expire(), cached.expireUnit());
			} else {
				cache.put(key, result);
			}
		}
		return result;
	}
}

CacheUpdateAspect

@CacheUpdate注解的切面實現(xiàn)類。

package com.morris.spring.custom.cache.annotation;
import com.morris.spring.custom.cache.Level2Cache;
import com.morris.spring.custom.cache.Level2CacheManage;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.context.annotation.Configuration;
import org.springframework.expression.EvaluationContext;
import javax.annotation.Resource;
@Configuration
@Aspect
public class CacheUpdateAspect {
	@Resource
	private Level2CacheManage cacheManager;
	@Around(value = "@annotation(cacheUpdate)")
	public Object around(ProceedingJoinPoint joinPoint, CacheUpdate cacheUpdate) throws Throwable {
		Level2Cache cache = cacheManager.getCache(cacheUpdate.cacheName());
		ExpressionEvaluator evaluator = new ExpressionEvaluator();
		EvaluationContext context = evaluator.createEvaluationContext(joinPoint);
		Object key = evaluator.key(cacheUpdate.key(), context);
		Object result = joinPoint.proceed();
		context.setVariable("result", result);
		Boolean condition = evaluator.condition(cacheUpdate.condition(), context);
		Boolean unless = evaluator.unless(cacheUpdate.unless(), context);
		if (condition && !unless) {
			if (cacheUpdate.expire() > 0) {
				cache.put(key, result, cacheUpdate.expire(), cacheUpdate.expireUnit());
			} else {
				cache.put(key, result);
			}
		}
		return result;
	}
}

CacheInvalidateAspect

@CacheInvalidate注解的切面實現(xiàn)類。

package com.morris.spring.custom.cache.annotation;
import com.morris.spring.custom.cache.Level2Cache;
import com.morris.spring.custom.cache.Level2CacheManage;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.context.annotation.Configuration;
import org.springframework.expression.EvaluationContext;
import javax.annotation.Resource;
@Configuration
@Aspect
public class CacheInvalidateAspect {
	@Resource
	private Level2CacheManage cacheManager;
	@Around(value = "@annotation(cacheInvalidate)")
	public Object around(ProceedingJoinPoint joinPoint, CacheInvalidate cacheInvalidate) throws Throwable {
		Level2Cache cache = cacheManager.getCache(cacheInvalidate.cacheName());
		ExpressionEvaluator evaluator = new ExpressionEvaluator();
		EvaluationContext context = evaluator.createEvaluationContext(joinPoint);
		Object key = evaluator.key(cacheInvalidate.key(), context);
		Object result = joinPoint.proceed();
		context.setVariable("result", result);
		Boolean condition = evaluator.condition(cacheInvalidate.condition(), context);
		Boolean unless = evaluator.unless(cacheInvalidate.unless(), context);
		if (condition && !unless) {
			cache.evict(key);
		}
		return result;
	}
}

ExpressionEvaluator

ExpressionEvaluator主要用于解析注解中key、condition、unless屬性中的表達式。

package com.morris.spring.custom.cache.annotation;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.aop.support.AopUtils;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.util.StringUtils;
import java.lang.reflect.Method;
public class ExpressionEvaluator {
	private final SpelExpressionParser parser = new SpelExpressionParser();
	public EvaluationContext createEvaluationContext(ProceedingJoinPoint joinPoint) {
		MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
		Method specificMethod = AopUtils.getMostSpecificMethod(methodSignature.getMethod(), joinPoint.getTarget().getClass());
		MethodBasedEvaluationContext context = new MethodBasedEvaluationContext(joinPoint.getTarget(),
				specificMethod, joinPoint.getArgs(), new DefaultParameterNameDiscoverer());
		return context;
	}
	public Object key(String keyExpression, EvaluationContext evalContext) {
		Expression expression = parser.parseExpression(keyExpression);
		return expression.getValue(evalContext);
	}
	public boolean condition(String conditionExpression, EvaluationContext evalContext) {
		if(!StringUtils.hasText(conditionExpression)) {
			return true;
		}
		Expression expression = parser.parseExpression(conditionExpression);
		return (Boolean.TRUE.equals(expression.getValue(evalContext, Boolean.class)));
	}
	public boolean unless(String unlessExpression, EvaluationContext evalContext) {
		if(StringUtils.hasText(unlessExpression)) {
			return false;
		}
		Expression expression = parser.parseExpression(unlessExpression);
		return (Boolean.TRUE.equals(expression.getValue(evalContext, Boolean.class)));
	}
}

總結

  • 自定義緩存注解使用了AOP的通知功能,所以需要開啟AOP,需要在配置類上加上@EnableAspectJAutoProxy注解。
  • 改進:可使用類似@EnableCache注解導入一個入口類,不再需要多個切面,多個注解的處理邏輯放在一起,參考Spring Cache。
  • 擴展:解析表達式可使用緩存,加快解析速度;方法上面支持多個@Cached注解。

到此這篇關于關于spring的自定義緩存注解分析的文章就介紹到這了,更多相關spring自定義緩存注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Spring Boot Maven 打包可執(zhí)行Jar文件的實現(xiàn)方法

    Spring Boot Maven 打包可執(zhí)行Jar文件的實現(xiàn)方法

    這篇文章主要介紹了Spring Boot Maven 打包可執(zhí)行Jar文件的實現(xiàn)方法,需要的朋友可以參考下
    2018-02-02
  • Java中的接口多繼承機制

    Java中的接口多繼承機制

    大家好,本篇文章主要講的是Java中的接口多繼承機制,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-02-02
  • JAVA序列化和反序列化的底層實現(xiàn)原理解析

    JAVA序列化和反序列化的底層實現(xiàn)原理解析

    這篇文章主要介紹了JAVA序列化和反序列化的底層實現(xiàn)原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-11-11
  • Java數(shù)據(jù)結構之雙向鏈表的實現(xiàn)

    Java數(shù)據(jù)結構之雙向鏈表的實現(xiàn)

    相較單鏈表,雙向鏈表除了data與next域,還多了一個pre域用于表示每個節(jié)點的前一個元素。這樣做給雙向鏈表帶來了很多優(yōu)勢。本文主要介紹了雙向鏈表的實現(xiàn),需要的可以參考一下
    2022-10-10
  • IDEA “Cannot resolve symbol”爆紅問題解決

    IDEA “Cannot resolve symbol”爆紅問題解決

    最近發(fā)現(xiàn)個問題,IDEA 無法識別同一個 package 里的其他類,將其顯示為紅色,本文就來介紹一下IDEA “Cannot resolve symbol”爆紅問題解決,感興趣的可以了解一下
    2023-10-10
  • Spring創(chuàng)建bean的幾種方式及使用場景

    Spring創(chuàng)建bean的幾種方式及使用場景

    本文主要介紹了Spring創(chuàng)建bean的幾種方式及使用場景,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-04-04
  • IDEA 卡住buid(編譯)不動的解決辦法

    IDEA 卡住buid(編譯)不動的解決辦法

    這篇文章主要介紹了IDEA 卡住buid(編譯)不動的解決辦法(適用于maven和gradle)及定位思路,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-10-10
  • Spring Boot非Web項目運行的方法

    Spring Boot非Web項目運行的方法

    這篇文章主要給大家介紹了關于Spring Boot非Web項目運行的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Spring Boot具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-09-09
  • Java銀行取錢線程安全問題實例分析

    Java銀行取錢線程安全問題實例分析

    這篇文章主要介紹了Java銀行取錢線程安全問題,結合具體實例形式分析了java使用線程操作模擬銀行取錢的相關安全問題,需要的朋友可以參考下
    2019-09-09
  • SpringBoot將Bean放入容器的五種方式

    SpringBoot將Bean放入容器的五種方式

    這篇文章給大家介紹了SpringBoot將Bean放入容器的五種方式,文中通過代碼示例給大家介紹的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下
    2024-02-02

最新評論

阿合奇县| 渝中区| 凤台县| 嵊州市| 监利县| 崇州市| 昌都县| 富宁县| 芦山县| 永福县| 麻栗坡县| 甘肃省| 历史| 海兴县| 蛟河市| 晋江市| 十堰市| 涟源市| 莱西市| 延寿县| 柘荣县| 土默特右旗| 扶绥县| 高安市| 花莲县| 城固县| 河南省| 宁城县| 达孜县| 临安市| 西和县| 汝南县| 西城区| 个旧市| 修水县| 达日县| 施秉县| 东莞市| 扎囊县| 阿拉善左旗| 韩城市|