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攔截的問題


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM