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

相关文章
|
2月前
|
缓存 NoSQL 关系型数据库
redis和缓存及相关问题和解决办法 什么是缓存预热、缓存穿透、缓存雪崩、缓存击穿
本文深入探讨了Redis缓存的相关知识,包括缓存的概念、使用场景、可能出现的问题(缓存预热、缓存穿透、缓存雪崩、缓存击穿)及其解决方案。
198 0
redis和缓存及相关问题和解决办法 什么是缓存预热、缓存穿透、缓存雪崩、缓存击穿
|
1月前
|
SQL 缓存 Java
MyBatis如何关闭一级缓存(分注解和xml两种方式)
MyBatis如何关闭一级缓存(分注解和xml两种方式)
67 5
|
1月前
|
存储 缓存 Java
Spring缓存注解【@Cacheable、@CachePut、@CacheEvict、@Caching、@CacheConfig】使用及注意事项
Spring缓存注解【@Cacheable、@CachePut、@CacheEvict、@Caching、@CacheConfig】使用及注意事项
131 2
|
3月前
|
缓存 Java 开发工具
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
三级缓存是Spring框架里,一个经典的技术点,它很好地解决了循环依赖的问题,也是很多面试中会被问到的问题,本文从源码入手,详细剖析Spring三级缓存的来龙去脉。
217 24
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
|
2月前
|
缓存 NoSQL Java
Springboot自定义注解+aop实现redis自动清除缓存功能
通过上述步骤,我们不仅实现了一个高度灵活的缓存管理机制,还保证了代码的整洁与可维护性。自定义注解与AOP的结合,让缓存清除逻辑与业务逻辑分离,便于未来的扩展和修改。这种设计模式非常适合需要频繁更新缓存的应用场景,大大提高了开发效率和系统的响应速度。
70 2
|
4月前
|
缓存 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` 依赖并使用特定注解实现缓存逻辑。
1139 1
SpringBoot的三种缓存技术(Spring Cache、Layering Cache 框架、Alibaba JetCache 框架)
|
4月前
|
缓存 分布式计算 Java
详细解读MapReduce框架中的分布式缓存
【8月更文挑战第31天】
49 0
|
4月前
|
开发框架 缓存 NoSQL
基于SqlSugar的开发框架循序渐进介绍(17)-- 基于CSRedis实现缓存的处理
基于SqlSugar的开发框架循序渐进介绍(17)-- 基于CSRedis实现缓存的处理
|
5月前
|
存储 缓存 开发框架
Winform框架中窗体基类的用户身份信息的缓存和提取
Winform框架中窗体基类的用户身份信息的缓存和提取
|
4月前
|
存储 缓存 Java
Java本地高性能缓存实践问题之使用@CachePut注解来更新缓存中数据的问题如何解决
Java本地高性能缓存实践问题之使用@CachePut注解来更新缓存中数据的问题如何解决