spring与redis集成之aop整合方案

java使用redis缓存可以使用jedis框架,jedis操作简单,没有什么复杂的东西需要学习,网上资料很多,随便看看就会了.

将spring与redis缓存集成,其实也是使用jedis框架,只不过spring对它进行了一层封装,并将这层封装库命名为spring-data-redis.

下面将要使用spring-data-redis与jedis的jar包,并通过spring的aop功能,将redis缓存无缝无侵入的整合进来.

1.先下载好依赖包


	org.springframework
	spring-core
	4.1.1.RELEASE

  
	org.springframework.data  
	spring-data-redis  
	1.4.1.RELEASE  
 
 
	redis.clients 
	jedis 
	2.6.0 
 

2.再配置spring文件

    
    	
          
          
          
          
      
    
    
        
        
        
        
        
     
    
	
	
		
		
			
			
		
			
		
		  
	         
	    
	    
	         
	    
	

3.开始编写aop代码

3.1 声明两个注解类,用于定义哪些方法将使用缓存

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Cacheable {
	
	public enum KeyMode{
		DEFAULT,	//只有加了@CacheKey的参数,才加入key后缀中
		BASIC,		//只有基本类型参数,才加入key后缀中,如:String,Integer,Long,Short,Boolean
		ALL;		//所有参数都加入key后缀
	}
	
	public String key() default "";		//缓存key
	public KeyMode keyMode() default KeyMode.DEFAULT;		//key的后缀模式
	public int expire() default 0;		//缓存多少秒,默认无限期
}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
public @interface CacheKey {}
3.2 创建一个Aop拦截器的处理类,用于拦截加了@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 valueOper=redisTemplate.opsForValue();
		Object value=valueOper.get(key);	//从缓存获取数据
		if(value!=null) return value;		//如果有数据,则直接返回
		
		value = pjp.proceed();		//跳过缓存,到后端查询数据
		if(cache.expire()<=0) {		//如果没有设置过期时间,则无限期缓存
			valueOper.set(key, value);
		} else {					//否则设置缓存时间
			valueOper.set(key, value,cache.expire(),TimeUnit.SECONDS);
		}
		return value;
	}
	
	/**
	 * 获取缓存的key值
	 * @param pjp
	 * @param cache
	 * @return
	 */
	private String getCacheKey(ProceedingJoinPoint pjp,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

4.使用缓存示例

@Service
@Transactional
public class DemoServiceImpl implements DemoService {

	@Autowired private DemoDao demoDao;

	public List findAll() {
		return demoDao.findAll();
	}
	
	/*
		对get()方法配置使用缓存,缓存有效期为3600秒,缓存的key格式为:{package_name}.DemoServiceImpl.get
		同时为参数配置了@CacheKey后,表示此参数的值将做为key的后缀,此例的key,最终是:{package_name}.DemoServiceImpl.get.{id}
		可以为多个参数配置@CacheKey,拦截器会调用参数的toString()做为key的后缀
		若配置多个@CacheKey参数,那么最终的key格式为:{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);
	}
}

  • 若为名称相同的方法配置缓存,可以在@Cacheable中加入key属性,追加额外的key后缀
  • @Cacheable还有一个KeyMode属性,用于配置哪些参数可以追加到key后缀中,
    默认取值 DEFAULT:表示只有加了@CacheKey的参数才能追加到key后缀
    BASIC:自动将基本类型追加到key后缀,而无需再配置@CacheKey
    ALL:自动将所有参数追加到lkey后缀,而无需再配置@CacheKey

这只是一个初步整合方案,测试可行,还未在生产中使用,实际效果待验正.

你可能感兴趣的:(spring,spring,redis,spring-data,aop)