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

關(guān)于spring的自定義緩存注解分析

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

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

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

@Cacheabe不能設(shè)置緩存時(shí)間,導(dǎo)致生成的緩存始終在redis中,當(dāng)然這一點(diǎn)可以通過修改RedisCacheManager的配置來設(shè)置緩存時(shí)間:

@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)); // 設(shè)置全局key的有效事件為7天
	return redisCacheConfiguration;
}

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

自定義緩存注解

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注解的切面實(shí)現(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注解的切面實(shí)現(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注解的切面實(shí)現(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屬性中的表達(dá)式。

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)));
	}
}

總結(jié)

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

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

相關(guān)文章

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

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

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

    Java中的接口多繼承機(jī)制

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

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

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

    Java數(shù)據(jù)結(jié)構(gòu)之雙向鏈表的實(shí)現(xiàn)

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

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

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

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

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

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

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

    Spring Boot非Web項(xiàng)目運(yùn)行的方法

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

    Java銀行取錢線程安全問題實(shí)例分析

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

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

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

最新評(píng)論

宜章县| 金塔县| 大丰市| 壤塘县| 溧水县| 泽库县| 武川县| 茶陵县| 怀化市| 什邡市| 太仆寺旗| 孟连| 封开县| 峨山| 苏尼特右旗| 江永县| 武鸣县| 昔阳县| 饶平县| 石屏县| 涞水县| 繁峙县| 贵州省| 吴忠市| 漳浦县| 闽清县| 新邵县| 贡嘎县| 大悟县| 安远县| 汤阴县| 达拉特旗| 康平县| 山阳县| 镇远县| 凉城县| 松桃| 理塘县| 乌兰浩特市| 大足县| 永吉县|