當前位置:
                    首頁 >
                            前端技术
>                            javascript
>内容正文                
                        
                    javascript
SpringAOP中通过JoinPoint获取值,并且实现redis注解
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                SpringAOP中通过JoinPoint获取值,并且实现redis注解
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
                                在Java8之前,代碼編譯為class文件后,方法參數的類型固定,但是方法名稱會丟失,方法名稱會變成arg0、arg1….。在Java8開始可以在class文件中保留參數名
public void tet(JoinPoint joinPoint) {// 下面兩個數組中,參數值和參數名的個數和位置是一一對應的。Object[] args = joinPoint.getArgs(); // 參數值String[] argNames = ((MethodSignature)joinPoint.getSignature()).getParameterNames(); // 參數名// 得到被代理的方法Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();// 得到被代理的方法上的注解Class modelType = method.getAnnotation(RedisCache.class).type();// 得到被代理方法的返回值類型Class returnType = ((MethodSignature) joinPoint.getSignature()).getReturnType() }@Cacheable注解作用,將帶有該注解方法的返回值存放到redis的的中;
 使用方法在方法上使用@Cacheable(鍵=“測試+#P0 + P1#…”)
 表示鍵值為測試+方法第一個參數+方法第二個參數,值為該方法的返回值。
 以下源代碼表示獲取人員列表,Redis的中存放的關鍵值為’領袖’+ leaderGroupId + UUID + yearDetailId
等同于
@Overridepublic List<Leader> listLeaders(String leaderGroupId, String uuid, String yearDetailId) {String key = "leader" + leaderGroupId + uuid + yearDetailId;// 判斷緩存是否存在redis中boolean hasKey = redisUtil.hasKey(key);if (hasKey) {//如果存在 返還redis中的值Object leadersList = redisUtil.get(key);return (List<Leader>) leadersList;} else {List<Leader> leadersQuotaDetailList = sysIndexMapper.listLeaders(leaderGroupId, uuid, yearDetailId);//將查詢結果存放在redis中redisUtil.set(key, leadersQuotaDetailList);return leadersQuotaDetailList;}}緩存配置類RedisConfig
package com.huajie.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper;/*** Redis緩存配置類*/ @Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport {@Value("${spring.redis.host}")private String host;@Value("${spring.redis.port}")private int port;@Value("${spring.redis.timeout}")private int timeout;// 自定義緩存key生成策略@Beanpublic KeyGenerator keyGenerator() {return new KeyGenerator() {@Overridepublic Object generate(Object target, java.lang.reflect.Method method, Object... params) {StringBuffer sb = new StringBuffer();sb.append(target.getClass().getName());sb.append(method.getName());for (Object obj : params) {sb.append(obj.toString());}return sb.toString();}};}// 緩存管理器@Beanpublic CacheManager cacheManager(@SuppressWarnings("rawtypes") RedisTemplate redisTemplate) {RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);// 設置緩存過期時間cacheManager.setDefaultExpiration(10000);return cacheManager;}@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();template.setConnectionFactory(factory);Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();// key采用String的序列化方式template.setKeySerializer(stringRedisSerializer);// hash的key也采用String的序列化方式template.setHashKeySerializer(stringRedisSerializer);// value序列化方式采用jacksontemplate.setValueSerializer(jackson2JsonRedisSerializer);// hash的value序列化方式采用jacksontemplate.setHashValueSerializer(jackson2JsonRedisSerializer);template.afterPropertiesSet();return template;}private void setSerializer(StringRedisTemplate template) {@SuppressWarnings({ "rawtypes", "unchecked" })Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);template.setValueSerializer(jackson2JsonRedisSerializer);} }Redis的依賴引入,配置文件,工具類RedisUtil,網上幾個版本都類似,本文參考以下版本傳送門
 https://www.jb51.net/article/233562.htm
 準備工作做好之后開始正式編寫注解@Cacheable nextkey()用做二級緩存本文中不會用到
 nextKey用法詳情> 設計模式(實戰) - 責任鏈模式 <
 創建的Java的注解@ExtCacheable
SpringAop切面CacheableAspect
package com.huajie.aspect; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.huajie.annotation.ExtCacheable; import com.huajie.utils.RedisUtil;/*** redis緩存處理* 不適用與內部方法調用(this.)或者private*/ @Component @Aspect public class CacheableAspect { @Autowiredprivate RedisUtil redisUtil;@Pointcut("@annotation(com.huajie.annotation.ExtCacheable)")public void annotationPointcut() {}@Around("annotationPointcut()")public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {// 獲得當前訪問的classClass<?> className = joinPoint.getTarget().getClass();// 獲得訪問的方法名String methodName = joinPoint.getSignature().getName();// 得到方法的參數的類型Class<?>[] argClass = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();Object[] args = joinPoint.getArgs();String key = "";int expireTime = 1800;try {// 得到訪問的方法對象Method method = className.getMethod(methodName, argClass);method.setAccessible(true);// 判斷是否存在@ExtCacheable注解if (method.isAnnotationPresent(ExtCacheable.class)) {ExtCacheable annotation = method.getAnnotation(ExtCacheable.class);key = getRedisKey(args,annotation);expireTime = getExpireTime(annotation);}} catch (Exception e) {throw new RuntimeException("redis緩存注解參數異常", e);}// 獲取緩存是否存在boolean hasKey = redisUtil.hasKey(key);if (hasKey) {return redisUtil.get(key);} else {//執行原方法(java反射執行method獲取結果)Object res = joinPoint.proceed();//設置緩存redisUtil.set(key, res);//設置過期時間redisUtil.expire(key, expireTime);return res;}}private int getExpireTime(ExtCacheable annotation) {return annotation.expireTime();}private String getRedisKey(Object[] args,ExtCacheable annotation) {String primalKey = annotation.key();//獲取#p0...集合List<String> keyList = getKeyParsList(primalKey);for (String keyName : keyList) {int keyIndex = Integer.parseInt(keyName.toLowerCase().replace("#p", ""));Object parValue = args[keyIndex];primalKey = primalKey.replace(keyName, String.valueOf(parValue));}return primalKey.replace("+","").replace("'","");}// 獲取key中#p0中的參數名稱private static List<String> getKeyParsList(String key) {List<String> ListPar = new ArrayList<String>();if (key.indexOf("#") >= 0) {int plusIndex = key.substring(key.indexOf("#")).indexOf("+");int indexNext = 0;String parName = "";int indexPre = key.indexOf("#");if(plusIndex>0){indexNext = key.indexOf("#") + key.substring(key.indexOf("#")).indexOf("+");parName = key.substring(indexPre, indexNext);}else{parName = key.substring(indexPre);}ListPar.add(parName.trim());key = key.substring(indexNext + 1);if (key.indexOf("#") >= 0) {ListPar.addAll(getKeyParsList(key));}}return ListPar;} }業務模塊使用方法
@Override@ExtCacheable(key = "Leaders+#p0+#p1+#p2")// 手機端獲取領導人員列表public List<Leader> listLeaders(String leaderGroupId, String uuid, String yearDetailId) {List<Leader> leadersQuotaDetailList = sysIndexMapper.listLeaders(leaderGroupId, uuid, yearDetailId);return leadersQuotaDetailList;}業務模塊過期時間使用方法,5分鐘過期
@Override@ExtCacheable(key = "mobileCacheFlag", expireTime = 60 * 5)public int cacheFlag() {int mobileCacheFlag = 1;mobileCacheFlag = sysIndexMapper.cacheFlag();return mobileCacheFlag;}總結
以上是生活随笔為你收集整理的SpringAOP中通过JoinPoint获取值,并且实现redis注解的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: Tomcat线程连接池参数优化
- 下一篇: 贪心思想草稿
