There are some business methods in the project that want to get directly from the cache when there is a cache, and no longer execute the method to increase throughput. And that's a lot of things. If you write an if else code for each method, it causes the coupling to be very large and inconvenient for later modification.
Reasoning, decided to use automatic annotations +spring AOP to implement.
Directly paste the code.
Custom annotation Classes:
Packagecom.ns.annotation;Importjava.lang.annotation.Documented;ImportJava.lang.annotation.ElementType;Importjava.lang.annotation.Retention;ImportJava.lang.annotation.RetentionPolicy;ImportJava.lang.annotation.Target;ImportJava.util.concurrent.TimeUnit;/** * * --------- * @authorHan*/@Target (Elementtype.method) @Retention (retentionpolicy.runtime) @Documented Public@Interfacerediscached {/*** Redis Key *@return */String value (); /*** Expiry time, default is 1 minutes, if you want to set never expires, set a value less than or equal to 0 *@return */ LongTimeout ()default1; /*** Time unit, default is minutes *@return */timeunit timeunit ()defaulttimeunit.minutes; /*** Extra defines an empty method that calls the method to update the previous cache *@return */ BooleanFordelete ()default false;}
This annotation makes it easy for us to mark that method as an entry point for AOP.
AOP implementations:
PackageCOM.NS.REDIS.AOP;ImportJava.lang.reflect.Method;ImportJava.util.concurrent.TimeUnit;Importorg.apache.commons.codec.digest.DigestUtils;Importorg.apache.commons.lang.ArrayUtils;ImportOrg.aspectj.lang.ProceedingJoinPoint;ImportOrg.aspectj.lang.annotation.Around;ImportOrg.aspectj.lang.annotation.Aspect;ImportOrg.aspectj.lang.annotation.Pointcut;Importorg.aspectj.lang.reflect.MethodSignature;Importorg.hibernate.metamodel.binding.Caching;ImportOrg.slf4j.Logger;Importorg.slf4j.LoggerFactory;Importorg.springframework.core.Ordered;ImportOrg.springframework.core.annotation.Order;Importorg.springframework.dao.DataAccessException;Importorg.springframework.data.redis.connection.RedisConnection;ImportOrg.springframework.data.redis.core.RedisCallback;ImportOrg.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;ImportOrg.springframework.data.redis.serializer.RedisSerializer;Importorg.springframework.stereotype.Component;Importcom.ns.annotation.RedisCached;ImportCom.ns.redis.dao.base.BaseRedisDao;/*** The cache processing of DAO's Getbean * Order guaranteed to take precedence over this facet *@authorHan*/@Aspect Public classAutorediscachedextendsBaseredisdao<object, object>Implementsordered{Private Static FinalLogger log = Loggerfactory.getlogger (redislockaspect.class); /** Constrain any method of the class containing DAO under any package, and be cached annotated*/@Pointcut ("Execution (* *.. *(..)) && @annotation (com.ns.annotation.RedisCached) ") Private voidCachemethod () {} @Around ("Cachemethod ()") PublicObject Doarround (Proceedingjoinpoint PJP)throwsthrowable{object[] args=Pjp.getargs (); Methodsignature methodsignature=(methodsignature) pjp.getsignature (); Method Method=Methodsignature.getmethod (); Finalrediscached cacheinfo = method.getannotation (rediscached.class); //Defining a serializer FinalRedisserializer<string> Keyserializer =Getstringserializer (); FinalRedisserializer ValueSerializer =NewJackson2jsonredisserializer (Method.getreturntype ()); //serialization parameters, as HashKey byte[] Keybytestemp =keyserializer.serialize (Cacheinfo.value ()); for(Object Arg:args) {keybytestemp=Arrayutils.addall (Keybytestemp, Getdefaultserializer (). Serialize (ARG)); } //take MD5 after key Final byte[] Keybytes =keyserializer.serialize (Digestutils.md5hex (keybytestemp)); //is the Delete method if(Cacheinfo.fordelete ()) {Execute (NewRediscallback<object>() {@Override PublicObject Doinredis (redisconnection connection)throwsDataAccessException {returnConnection.del (keybytes); } }); return NULL; } Object obj=NULL; Log.info ("Method" +method.getname () + "tangent, attempt to get from cache ..."); Obj= Execute (NewRediscallback<object>() {@Override PublicObject Doinredis (redisconnection connection)throwsDataAccessException {byte[] tmp =Connection.get (keybytes); returnvalueserializer.deserialize (TMP); } }); if(obj = =NULL) {Log.info ("Method" +method.getname () + "tangent, cache not found ..."); FinalObject Objreturn =pjp.proceed (); if(Objreturn! =NULL) {Execute (NewRediscallback<boolean>() {@Override PublicBoolean Doinredis (redisconnection connection)throwsDataAccessException {if(Cacheinfo.timeout () > 0) {Connection.setex (keybytes, TimeUnit.SECONDS.convert (Cacheinfo.timeout (), Cacheinfo.timeu NIT ()), Valueserializer.serialize (Objreturn)); }Else{connection.set (keybytes,valueserializer.serialize (Objreturn)); } return true; } }); } obj=Objreturn; }Else{log.info ("Method" +method.getname () + "slice, Cache hit ..."); } //get from DAO returnobj; } @Override Public intGetOrder () {return-1; }}
Note: The Orderd interface is designed to ensure that this code takes precedence over other facets of execution.
In-depth understanding of the use of Spring Redis (eight), spring Redis implementation Note Auto-caching