基于@AspectJ的Aop来实现缓存控制报NoSuchMethodException

2 篇文章 0 订阅
1 篇文章 0 订阅

项目中基于@Aspect实现AOP,通过环绕增强(@Around)控制Dao的缓存(set/delete)。DAO接口及实现及AOP部分代码如下:

 

///
package cn.xxx.dao;
public interface FunModuleDao {
	/**
	 * 更新用户视图布局
	 * 
	 * @param userId	用户ID
	 * @param fmlList	布局对象列表
	 */
	public void updateFunModuleUsers(Long userId,List fmlList);

}

//
package cn.xxx.dao.impl;
@Repository
public class FunModuleDaoImpl implements FunModuleDao {
        @Override
	@CacheEvict(prefix = "userCache",  suffix="0")
        public void updateFunModuleUsers(Long userId,List fmlList){

           代码略..
        }


package cn.xxx.cache.aop;
  
@Component  
@Aspect  
public class CacheAop {  
	private static final Log log = LogFactory.getLog(CacheAop.class);
	@Autowired
	private SiteService siteService;  
	
	@Autowired
	private MemKeyService memKeyService;
	
	@Autowired
	private MemCachedClient memCachedClient ; 
	
	@Around(value="@annotation(cn.xxx.cache.annotation.Cacheable)")
    public Object cache(ProceedingJoinPoint call){  
         Object result = null;  
         Boolean cacheEnable = CustomizedPropertyPlaceholderConfigurer.getCacheEnabled();
         //判断是否开启缓存
         if(!cacheEnable){
             try {
                 result= call.proceed();
             } catch (Throwable e) {
                 e.printStackTrace();
             }
             return result;
         }

         Method method=getMethod(call);
         Cacheable cacheable=method.getAnnotation(cn.ac.ucas.sep.cache.annotation.Cacheable.class);
         
         String fieldKey =parseKey(cacheable.suffix(),method,call.getArgs());
         String prefix = cacheable.prefix();  
         String cacheKey = prefix+"_"+fieldKey;  
         
         result =memCachedClient.get(cacheKey); 
         
         if(null == result){  
             try {  
                 result = call.proceed();  
                 long expiration = cacheable.expiration();//1000*60*60*48==48小时过期   
                 Date expirationTime=new Date(System.currentTimeMillis()+expiration);  
                 memCachedClient.set(cacheKey, result,expirationTime));
             } catch (Throwable e) {  
                 e.printStackTrace();  
             }  
         }
        return result;  
    }  
    
	/**
	 * 定义清除缓存逻辑         
	 */
    @Around(value="@annotation(cn.xxx.cache.annotation.CacheEvict)")
    public Object evict(ProceedingJoinPoint call){
    	代码略...
    }

	/**
     *  获取被拦截方法对象
     *  
     *  MethodSignature.getMethod() 获取的是顶层接口或者父类的方法对象
     *  而缓存的注解在实现类的方法上
     *  所以应该使用反射获取当前对象的方法对象
     */
    public Method getMethod(ProceedingJoinPoint call){
        //获取参数的类型
        Object [] args=call.getArgs();
        Class [] argTypes=new Class[call.getArgs().length];
        for(int i=0;i<args.length;i++){
    		argTypes[i]=args[i].getClass();
        }
        Method method=null;
        try {
            method=call.getTarget().getClass().getMethod(call.getSignature().getName(),argTypes);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
        return method;
        
    }
    /**
     * 获取缓存的key 
     * key 定义在注解上,支持SPEL表达式
     */
    private String parseKey(String key,Method method,Object [] args){
        代码略...
    }

}  

 

 

运行调试过程中出现一个很诡异的问题,错误信息如下:

 

java.lang.NoSuchMethodException: cn.xxx.dao.impl.FunModuleDaoImpl.updateFunModuleUsers(java.lang.Long, java.util.ArrayList)
	at java.lang.Class.getMethod(Class.java:1607)
        at cn.ac.ucas.sep.cache.aop.CacheAop.getMethod(CacheAop.java:148)

//CacheAop.java:148即method=call.getTarget().getClass().getMethod(call.getSignature().getName(),argTypes);

 跟踪执行过程最终找到原因:

 

通过ProceedingJoinPoint.getArgs()[1].getClass()获取的第二个参数类型(java.util.ArrayList)与call.getTarget().getClass().getMethod(...)中的类型(java.util.List)不匹配造成的。

 

解决办法:

修改Dao接口和实现的参数类型由List变为ArrayList

 

///
package cn.xxx.dao;
public interface FunModuleDao {
	/**
	 * 更新用户视图布局
	 * 
	 * @param userId	用户ID
	 * @param fmlList	布局对象列表
	 */
	public void updateFunModuleUsers(Long userId,ArrayList fmlList);

}

//
package cn.xxx.dao.impl;
@Repository
public class FunModuleDaoImpl implements FunModuleDao {
        @Override
	@CacheEvict(prefix = "userCache",  suffix="0")
        public void updateFunModuleUsers(Long userId,ArrayList fmlList){

           代码略..
        }

 

 

 获取还有更好的办法,暂时先用上吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值