在Shiro框架内使用缓存注解失效的解决办法

这个问题困扰了我好多天

问题

  1. ServiceImpl类里的方法上有缓存注解,用于将返回的实体类存入redis,下次调用时就不需要通过数据库获取实体类信息。
  2. Shiro框架内由于自定义了Ream,需要注入Service来获取用户实体类信息。
  3. 而后运行时,发现缓存注解并没有起作用,两次调用Service方法,都进入了方法,而不是读取缓存。
  • 自定义Ream
/**
 * 用来给shiro注入认证信息和授权信息
 */
@Component("userRealm")
public class UserRealm extends AuthorizingRealm{

    /**
     * shiro内注入bean时,需要加入lazy注解,否则bean可能不能正常运行(比如缓存注解)
     * 参考:https://blog.csdn.net/elonpage/article/details/78965176
     */
    @Autowired
    @Lazy
    private UserService userService;

    /**
     * 授权处理
     * 登录时不检查用户权限
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }

    /**
     * 身份认证
     *
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 获取用户 - 这里调用了Service方法
        String account = (String) authenticationToken.getPrincipal();
        User user = userService.getUserByAccount(account,
                DatabaseConst.STATUS_ENABLE,
                DatabaseConst.IS_DETETED_NO);
        if (user  == null) {
            return null;
        }

        return new SimpleAuthenticationInfo(
                user,
                user.getPassword().toCharArray(),
                ByteSource.Util.bytes("salt-sdwbhx23i"),//盐,可自定义
                getName()
        );
    }
}
  • Service方法
@Service
public class UserServiceImpl implements UserService{
    // 使用了缓存注解的方法,第二次执行时,应该直接从缓存中读取User实体信息
    @Cacheable(value = RedisConst.USER_INFO ,key = "#account")
    public User getUserByAccount(String account,int isEnable,int isDeleted) {
        //这里模拟从数据库中读取数据
        User user = new User();
        user.setAccount(account);
        user.setIsDeleted(isDeleted);
        user.setStatus(isEnable);
        return userMapper.selectOne(user);
    }
}

解决办法

在Shiro框架内注入bean时,除了 @Autowired 注解外,再加入 @Lazy 注解。
这样会使得注入到Shiro框架的Bean延时加载(即在第一次使用的时候加载)

原因

spring boot整合shiro后,部分注解(Cache缓存、Transaction事务等)失效的问题
简单来说,就是Shiro框架初始化比Spring框架的某些部件早,导致使用@Autowire注入Shiro框架的某些类不能被Spring正确初始化。

上一篇:关于SQL语句的一些细节


下一篇:Shiro和SpringBoot简单集成