Java開發(fā)框架spring實現(xiàn)自定義緩存標(biāo)簽
自從spring3.1之后,spring引入了抽象緩存,可以通過在方法上添加@Cacheable等標(biāo)簽對方法返回的數(shù)據(jù)進(jìn)行緩存。但是它到底是怎么實現(xiàn)的呢,我們通過一個例子來看一下。首先我們定義一個@MyCacheable
package caching.springaop; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.annotation.ElementType; /** * 使用@MyCacheable注解方法 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MyCacheable{ }
然后定義處理MyCacheable的切面
package caching.springaop; import java.util.HashMap; import java.util.Map; import org.apache.log4j.Logger; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; /** * 處理MyCacheable方法的切面 */ @Aspect public class CacheAspect { private Logger logger = Logger.getLogger(CacheAspect.class); private Map<String, Object> cache; public CacheAspect() { cache = new HashMap<String, Object>(); } /** * 所有標(biāo)注了@Cacheable標(biāo)簽的方法切入點 */ @Pointcut("execution(@MyCacheable * *.*(..))") @SuppressWarnings("unused") private void cache() { } @Around("cache()") public Object aroundCachedMethods(ProceedingJoinPoint thisJoinPoint) throws Throwable { logger.debug("Execution of Cacheable method catched"); //產(chǎn)生緩存數(shù)據(jù)的key值,像是這個樣子caching.aspectj.Calculator.sum(Integer=1;Integer=2;) StringBuilder keyBuff = new StringBuilder(); //增加類的名字 keyBuff.append(thisJoinPoint.getTarget().getClass().getName()); //加上方法的名字 keyBuff.append(".").append(thisJoinPoint.getSignature().getName()); keyBuff.append("("); //循環(huán)出cacheable方法的參數(shù) for (final Object arg : thisJoinPoint.getArgs()) { //增加參數(shù)的類型和值 keyBuff.append(arg.getClass().getSimpleName() + "=" + arg + ";"); } keyBuff.append(")"); String key = keyBuff.toString(); logger.debug("Key = " + key); Object result = cache.get(key); if (result == null) { logger.debug("Result not yet cached. Must be calculated..."); result = thisJoinPoint.proceed(); logger.info("Storing calculated value '" + result + "' to cache"); cache.put(key, result); } else { logger.debug("Result '" + result + "' was found in cache"); return result; } }
上述代碼展示了如何處理MyCacheable自定義的標(biāo)簽,以及默認(rèn)情況下產(chǎn)生key值的規(guī)則。最后生成的key值大概是這個樣子:caching.aspectj.Calculator.sum(Integer=1;Integer=2;)
下邊這段代碼在方法上添加了MyCacheable標(biāo)簽
package caching.springaop; import org.apache.log4j.Logger; public class Calculator { private Logger logger = Logger.getLogger(Calculator.class); @MyCacheable public int sum(int a, int b) { logger.info("Calculating " + a + " + " + b); try { //假設(shè)這是代價非常高的計算 Thread.sleep(3000); } catch (InterruptedException e) { logger.error("Something went wrong...", e); } return a + b; } }
在方法上加了MyCacheable標(biāo)簽,當(dāng)key值相同的情況下會直接在緩存中獲取數(shù)據(jù),如果沒有相同的key值,則會重新計算,因為這里只是一個加和操作,耗時非常的短暫。我們在這里讓其睡眠3秒鐘。
我們在spring-config.xml配置如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <aop:aspectj-autoproxy /> <bean class="caching.springaop.CacheAspect" /> <bean id="calc" class="caching.springaop.Calculator" /> </beans>
測試類:
package caching.springaop; import org.apache.log4j.Logger; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * 使用SpringAOP緩存的簡單例子 * @author txxs */ public class App { private static Logger logger = Logger.getLogger(App.class); public static void main(String[] args) { logger.debug("Starting..."); ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml"); Calculator calc = (Calculator) ctx.getBean("calc"); //計算出來的結(jié)果將會被存儲在cache logger.info("1 + 2 = " + calc.sum(1, 2)); //從緩存中獲取結(jié)果 logger.info("1 + 2 = " + calc.sum(1, 2)); logger.debug("Finished!"); } }
我們看一下運行的結(jié)果:
從結(jié)果來看第一次直接計算結(jié)果,第二次從緩存中獲取。
以上就是spring實現(xiàn)自定義緩存標(biāo)簽的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助
相關(guān)文章
Java修改eclipse中web項目的server部署路徑問題
這篇文章主要介紹了Java修改eclipse中web項目的server部署路徑,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-11-11Mybatis批量插入Oracle數(shù)據(jù)的方法實例
在開發(fā)中或多或少都會遇到數(shù)據(jù)批量插入的功能,最近我在做項目的過程中就遇到了這樣一個問題,下面這篇文章主要給大家介紹了關(guān)于Mybatis批量插入Oracle數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下2022-01-01Java判斷object對象為空(包括null ,““)的方法
這篇文章主要介紹了Java判斷對象是否為空(包括null ,“”)的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-12-12解決Springboot中Feignclient調(diào)用時版本問題
這篇文章主要介紹了解決Springboot中Feign?client調(diào)用時版本問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03在Spring AOP中代理對象創(chuàng)建的步驟詳解
今天和小伙伴們聊一聊 Spring AOP 中的代理對象是怎么創(chuàng)建出來的,透過這個過程再去熟悉一下 Bean 的創(chuàng)建過程,感興趣的小伙伴跟著小編一起來看看吧2023-08-08