zoukankan      html  css  js  c++  java
  • Spring的Bean内部方法调用无法使用AOP切面(CacheAble注解失效)

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

    问题复现

    @Service
    public 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方法中使用
    @Service
    public 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拦截的问题

  • 相关阅读:
    UUID工具类
    jax-rs 标准以及 结合 resteasy的使用
    Mina.Net实现的断线重连
    Mina.Net实现的UDP协议消息收发Demo
    MySql 比Replace Into更适合的用法,外加SqlServer的方式。
    MySql【Insert Select Not Exist】判断记录再添加值的方案
    MySql中存储过程中的@变量总是无法执行,提示Parameter '@XXX' must be defined
    Go语言使用Beego的ORM插入Mysql后,时区不一致的解决方案
    Go语言中Path包用法
    C#(WPF和WinForm)在普通类中调用到主线程的方法,SynchronizationContext的用法。
  • 原文地址:https://www.cnblogs.com/dudadi/p/8087664.html
Copyright © 2011-2022 走看看