Spring的Bean内部方法调用无法使用AOP切面(CacheAble注解失效)

来源:互联网 发布:jquery parsehtml源码 编辑:程序博客网 时间:2024/06/03 20:52

Spring的Bean内部方法调用无法使用AOP切面(CacheAble注解失效)

前言

今天在使用Spring cache的Cacheable注解的过程中遇见了一个Cacheable注解失效的问题,检查问题发生的原因是因为Spring的Cacheable注解是基于Spring AOP实现的,但是类内部方法互相调用时不会被Spring AOP拦截的,所以导致被调用方法的Cacheable注解失效,特此记录。

问题复现

@Servicepublic class UserServiceImpl{    @Override    public User detail(Long id) {            // 校验信息        if (id == null || id == 0) {            return ApiResult.instance().fail(UserResultEnum.USER_ID_NULL);        }        User user = this.selectById(id);        if (user == null) {            return ApiResult.instance().fail(UserResultEnum.USER_NULL);        }        return user;    }      @Override    @Cacheable(value = "user",condition = "#id != null", key = "'user'.concat(#id.toString())")    public User selectById(Serializable id){        return super.selectById(id);    }}

上述代码在使用this.selectById的时候Cacheable注解是无效的,解决办法如下:

  • 写一个工具类SpringContextUtil实现ApplicationContextAware接口
public class SpringContextUtil implements ApplicationContextAware {    private static ApplicationContext applicationContext;        @Override    public void setApplicationContext(ApplicationContext applicationContext){        SpringContextUtil.applicationContext = applicationContext;    }        public static ApplicationContext getApplicationContext(){        return applicationContext;    }        public static Object getBean(Class var1) throws BeansException {        return applicationContext.getBean(var1);    }}
  • 在Spring Boot启动的时候将ApplicationContext注入SpringContextUtil
public class AuthServiceApplication {    public static void main(String[] args) {        SpringContextUtil springContextUtil = new SpringContextUtil();        ApplicationContext applicationContext = SpringApplication.run(AuthServiceApplication.class, args);        springContextUtil.setApplicationContext(applicationContext);    }}
  • 在UserServiceImpl方法中使用
@Servicepublic class UserServiceImpl{    @Override    public User detail(Long id) {            // 校验信息        if (id == null || id == 0) {            return ApiResult.instance().fail(UserResultEnum.USER_ID_NULL);        }        //注入当前Bean使得调用内部方法也被SpringAOP拦截        IUserService userService = (IUserService) SpringContextUtil.getBean(this.getClass());        User user = userService.selectById(id);        if (user == null) {            return ApiResult.instance().fail(UserResultEnum.USER_NULL);        }        return user;    }      @Override    @Cacheable(value = "user",condition = "#id != null", key = "'user'.concat(#id.toString())")    public User selectById(Serializable id){        return super.selectById(id);    }}

这样就可以解决Bean内部方法调用不被Spring AOP拦截的问题

阅读全文
0 0