Integration of spring and redis into an AOP integration solution

Source: Internet
Author: User
Tags aop redis tostring

Java uses the Redis cache can use the Jedis framework, Jedis operation is simple, there is nothing complicated need to learn, the online material is many, casually look at it.

Integrating spring with the Redis cache is in fact using the Jedis framework, except that spring encapsulates it in a layer and names this layer of encapsulation as Spring-data-redis.

The following will use the Spring-data-redis and Jedis jar packages and integrate the Redis cache seamlessly without intrusion through spring's AOP capabilities.

1. Download the dependency package first

<dependency>
	<groupId>org.springframework</groupId>
	<artifactid>spring-core </artifactId>
	<version>4.1.1.RELEASE</version>
</dependency>
<!-- There are other spring packages, which are not affixed here--

<dependency>  
	<groupId>org.springframework.data</groupId>  
	<artifactId> spring-data-redis</artifactid>  
	<version>1.4.1.RELEASE</version>  
</dependency> 
<dependency> 
	<groupId>redis.clients</groupId> 
	<artifactid>jedis</ Artifactid> 
	<version>2.6.0</version> 

2. Configure the Spring file again

    <bean id= "Poolconfig" class= "Redis.clients.jedis.JedisPoolConfig" > <property name= "minidle" value= "${red Is.minidle} "/> <property name=" Maxidle "value=" ${redis.maxidle} "/> <property name=" MaxTota L "value=" ${redis.maxactive} "/> <property name=" Maxwaitmillis "value=" ${redis.maxwait} "/> & Lt;property name= "Testonborrow" value= "${redis.testonborrow}"/> </bean> <bean id= "jedisconnf Actory "class=" org.springframework.data.redis.connection.jedis.JedisConnectionFactory "> <property name=" hos Tname "value=" ${redis.host} "/> <property name=" port "value=" ${redis.port} "/> <property name= "Password" value= "${redis.password}"/> <property name= "Usepool" value= "true"/> <property nam E= "Poolconfig" ref= "Poolconfig"/> </bean> <!--redis template definition--<bean id= "Redi Stemplate "class=" Org.sprIngframework.data.redis.core.RedisTemplate "> <property name=" connectionfactory "ref=" Jedisconnfactory "/> <property name= "Keyserializer" > <bean class= " Org.springframework.data.redis.serializer.StringRedisSerializer "/> </property> <property name=" ValueSerializer "> <bean class=" Org.springframework.data.redis.serializer.JdkSerializationRedisSerializer "/ > </property> <property name= "Hashkeyserializer" > <bean class= "org.springframework.data.re
	       Dis.serializer.StringRedisSerializer "/> </property> <property name=" Hashvalueserializer "> <bean class= "Org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> </property&gt
	; </bean>

3. Start writing AOP code

3.1 Declares two annotation classes that define which methods will use the cache

@Retention (retentionpolicy.runtime)
@Target ({elementtype.method}) public
@interface cacheable {
	
	public enum keymode{
		DEFAULT,	//Only add the @cachekey parameter, add the key suffix
		basic,		//Only the basic type parameter, add the key suffix, such as: String, Integer,long,short,boolean all
		;		All parameters are added to the key suffix
	} public
	
	String key () default "";		Cache key Public
	Keymode Keymode () default keymode.default;		The suffix mode of key is public
	int expire () default 0;		Cache number of seconds, default indefinitely
}

@Retention (retentionpolicy.runtime)
@Target ({elementtype.parameter}) public
@interface CacheKey {}
3.2 Create a processing class for an AOP interceptor to intercept the method that adds the @cacheable

@Aspect @Component public class Cacheableaop {@Autowired private redistemplate redistemplate;
		
		@Around ("@annotation (cache)") public Object Cached (final proceedingjoinpoint pjp,cacheable cache) throws Throwable {
		String Key=getcachekey (PJP, cache);
		Valueoperations<string, object> valueoper=redistemplate.opsforvalue ();	Object Value=valueoper.get (key);		Get data from Cache if (value!=null) return value;		If there is data, return the value = Pjp.proceed () directly;
		Skip cache, to back-end query data if (Cache.expire () <=0) {//If no expiration time is set, the cache is Valueoper.set indefinitely (key, value);
		} else {//otherwise set cache time Valueoper.set (key, Value,cache.expire (), timeunit.seconds);
	} return value; /** * Gets the cached key value * @param PJP * @param cache * @return */private String Getcachekey (Proceedingjoinpoint PJ
		P,cacheable cache) {StringBuilder buf=new StringBuilder (); Buf.append (Pjp.getsignature (). Getdeclaringtypename ()). Append (".").
		Append (Pjp.getsignature (). GetName ()); if (Cache.key (). Length () >0) {Buf.apPend (".").
		Append (Cache.key ());
		} object[] Args=pjp.getargs (); if (Cache.keymode () ==keymode.default) {annotation[][] pas= ((methodsignature) pjp.getsignature ()). GetMethod ().
			Getparameterannotations (); for (int i=0;i<pas.length;i++) {to (Annotation An:pas[i]) {if (an instanceof CacheKey) {buf.append (".")
						). Append (Args[i].tostring ());
					Break
					}}}} and Else if (Cache.keymode () ==keymode.basic) {for (Object Arg:args) {if (arg instanceof String) { Buf.append (".").
				Append (ARG); } else if (arg instanceof Integer | | arg instanceof Long | | arg instanceof short) {Buf.append (".").
				Append (arg.tostring ()); } else if (arg instanceof Boolean) {buf.append (".").
				Append (arg.tostring ()); }}} and Else if (Cache.keymode () ==keymode.all) {for (Object Arg:args) {buf.append (".").
			Append (arg.tostring ());
	}} return buf.tostring (); }
}

4. Using the cache example

@Service
@Transactional Public
class Demoserviceimpl implements Demoservice {

	@Autowired private Demodao Demodao;

	Public list<demo> FindAll () {
		return demodao.findall ();
	}
	
	/* Cache is used for the
		get () method configuration, the cache is valid for 3,600 seconds, and the cache key format is: {package_name}. After the Demoserviceimpl.get
		has been configured with @cachekey for the parameter, the value of this parameter will be the suffix of key, the key of this example, and finally: {package_name}. Demoserviceimpl.get. {ID}
		@cachekey can be configured for multiple parameters, the interceptor invokes the parameter's ToString () as the key suffix
		If you configure multiple @cachekey parameters, the final key format is: {package_name}.{ Class_name}. {method}. {arg1}. {arg2}. {...}
	 */
	@Cacheable (expire=3600) public
	Demo get (@CacheKey String ID) {
		return demodao.get (ID);
	}

	Public Demo getbyname (String name) {
		return demodao.getbyname (name);
	}
}

If you configure the cache for the same name, you can add the key attribute to the @cacheable, append an additional key suffix @Cacheable and a Keymode property to configure which parameters can be appended to the key suffix.
Default value defaults: Indicates that only @cachekey parameters can be appended to the key suffix
Basic: Automatically appends the base type to the key suffix without having to configure the @cachekey
All: Automatically appends all parameters to the Lkey suffix without having to configure the @cachekey

This is only a preliminary integration program, testing feasible, not yet used in production, the actual effect to be tested positive.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.