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

简介: 这个问题困扰了我好多天问题ServiceImpl类里的方法上有缓存注解,用于将返回的实体类存入redis,下次调用时就不需要通过数据库获取实体类信息。

这个问题困扰了我好多天

问题

  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正确初始化。

相关文章
|
6天前
|
缓存 Java 开发工具
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
三级缓存是Spring框架里,一个经典的技术点,它很好地解决了循环依赖的问题,也是很多面试中会被问到的问题,本文从源码入手,详细剖析Spring三级缓存的来龙去脉。
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
|
1月前
|
缓存 NoSQL Java
SpringBoot的三种缓存技术(Spring Cache、Layering Cache 框架、Alibaba JetCache 框架)
Spring Cache 是 Spring 提供的简易缓存方案,支持本地与 Redis 缓存。通过添加 `spring-boot-starter-data-redis` 和 `spring-boot-starter-cache` 依赖,并使用 `@EnableCaching` 开启缓存功能。JetCache 由阿里开源,功能更丰富,支持多级缓存和异步 API,通过引入 `jetcache-starter-redis` 依赖并配置 YAML 文件启用。Layering Cache 则提供分层缓存机制,需引入 `layering-cache-starter` 依赖并使用特定注解实现缓存逻辑。
248 1
SpringBoot的三种缓存技术(Spring Cache、Layering Cache 框架、Alibaba JetCache 框架)
|
20天前
|
缓存 分布式计算 Java
详细解读MapReduce框架中的分布式缓存
【8月更文挑战第31天】
12 0
|
1月前
|
开发框架 缓存 NoSQL
基于SqlSugar的开发框架循序渐进介绍(17)-- 基于CSRedis实现缓存的处理
基于SqlSugar的开发框架循序渐进介绍(17)-- 基于CSRedis实现缓存的处理
|
2月前
|
存储 缓存 开发框架
Winform框架中窗体基类的用户身份信息的缓存和提取
Winform框架中窗体基类的用户身份信息的缓存和提取
|
30天前
|
存储 缓存 Java
Java本地高性能缓存实践问题之使用@CachePut注解来更新缓存中数据的问题如何解决
Java本地高性能缓存实践问题之使用@CachePut注解来更新缓存中数据的问题如何解决
|
1月前
|
存储 缓存 Java
Java本地高性能缓存实践问题之使用@CachePut注解来更新缓存中的数据的问题如何解决
Java本地高性能缓存实践问题之使用@CachePut注解来更新缓存中的数据的问题如何解决
|
2月前
|
设计模式 存储 缓存
Java面试题:结合设计模式与并发工具包实现高效缓存;多线程与内存管理优化实践;并发框架与设计模式在复杂系统中的应用
Java面试题:结合设计模式与并发工具包实现高效缓存;多线程与内存管理优化实践;并发框架与设计模式在复杂系统中的应用
40 0
|
6天前
|
canal 缓存 NoSQL
Redis缓存与数据库如何保证一致性?同步删除+延时双删+异步监听+多重保障方案
根据对一致性的要求程度,提出多种解决方案:同步删除、同步删除+可靠消息、延时双删、异步监听+可靠消息、多重保障方案
Redis缓存与数据库如何保证一致性?同步删除+延时双删+异步监听+多重保障方案
|
23天前
|
缓存 NoSQL Java
Redis深度解析:解锁高性能缓存的终极武器,让你的应用飞起来
【8月更文挑战第29天】本文从基本概念入手,通过实战示例、原理解析和高级使用技巧,全面讲解Redis这一高性能键值对数据库。Redis基于内存存储,支持多种数据结构,如字符串、列表和哈希表等,常用于数据库、缓存及消息队列。文中详细介绍了如何在Spring Boot项目中集成Redis,并展示了其工作原理、缓存实现方法及高级特性,如事务、发布/订阅、Lua脚本和集群等,帮助读者从入门到精通Redis,大幅提升应用性能与可扩展性。
49 0