经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Spring Boot » 查看文章
详谈@Cacheable不起作用的原因:bean未序列化问题
来源:jb51  时间:2022/1/3 12:31:25  对本文有异议

@Cacheable不起作用的原因:bean未序列化

SpringMVC中将serviceImpl的方法返回值缓存在redis中,发现@Cacheable失效

是返回的Blogger自定义实体类没有实现序列化接口

无法存入到redis中。implements一下Serializable接口即可!

@Cacheable注解式缓存不起作用的情形

@Cacheable注解式缓存使用的要点:正确的注解式缓存配置,注解对象为spring管理的hean,调用者为另一个对象。有些情形下注解式缓存是不起作用的:同一个bean内部方法调用,子类调用父类中有缓存注解的方法等。后者不起作用是因为缓存切面必须走代理才有效,这时可以手动使用CacheManager来获得缓存效果。

使用注解式缓存的正确方式

  1. <cache:annotation-driven cache-manager="springCacheManager" proxy-target-class="false"/>
  2. <bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
  3. ? ? <property name="configLocation" value="classpath:ehcache.xml"/>
  4. ? ? <property name="cacheManagerName" value="ehcache"/>
  5. </bean>
  6. <bean id="springCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
  7. ?? ?<property name="cacheManager" ref="ehcacheManager"/>
  8. </bean>

要点:@Cacheable(value="必须使用ehcache.xml已经定义好的缓存名称,否则会抛异常")

  1. @Component
  2. public class CacheBean {
  3. ?? ?@Cacheable(value="passwordRetryCache",key="#key")
  4. ?? ?public String map(String key) {
  5. ?? ??? ?System.out.println("get value for key: "+key);
  6. ?? ??? ?return "value: "+key;
  7. ?? ?}
  8. ?? ?public String map2(String key) {
  9. ?? ??? ?return map(key);
  10. ?? ?}
  11. }
  12. @RunWith(SpringJUnit4ClassRunner.class)
  13. @ContextConfiguration(locations = { "classpath:cache.xml" })
  14. public class CacheTester {
  15. ?? ?@Autowired CacheManager cacheManager;
  16. ?? ?@Autowired CacheBean cacheBean;
  17. ?? ?@Test public void cacheManager() {
  18. ?? ??? ?System.out.println(cacheManager);
  19. ?? ?}
  20. ?? ?@Test public void cacheAnnotation() {
  21. ?? ??? ?cacheBean.map("a");
  22. ?? ??? ?cacheBean.map("a");
  23. ?? ??? ?cacheBean.map("a");
  24. ?? ??? ?cacheBean.map("a");
  25. ?? ??? ?System.out.println(cacheManager.getCacheNames());
  26. ?? ?}
  27. }

输出:

get value for key: a
[authorizationCache, authenticationCache, shiro-activeSessionCache, passwordRetryCache]

稍微改造一下,让ehcache支持根据默认配置自动添加缓存空间,这里提供自定义的MyEhCacheCacheManager即可

  1. <bean id="springCacheManager" class="com.itecheast.ite.domain.util.MyEhCacheCacheManager">
  2. ?? ?<property name="cacheManager" ref="ehcacheManager"/>
  3. </bean>

另一种改造方式,找不到已定义的缓存空间时不缓存,或者关闭全部缓存。把cacheManagers配置去掉就可以关闭圈闭缓存。

  1. <bean id="springCacheManager" class="org.springframework.cache.support.CompositeCacheManager">
  2. ?? ?<property name="cacheManagers">
  3. ?? ??? ?<list>
  4. ?? ??? ??? ?<bean class="org.springframework.cache.ehcache.EhCacheCacheManager"></bean>
  5. ?? ??? ??? ?<!-- <bean class="com.itecheast.ite.domain.util.MyEhCacheCacheManager"></bean> 这个会自动创建缓存空间 -->
  6. ?? ??? ?</list>
  7. ?? ?</property>
  8. ? ? <property name="fallbackToNoOpCache" value="true"/>
  9. </bean>

调用相同类或父类方法没有缓存效果:这时可以选择手动使用CacheManager。

  1. @RunWith(SpringJUnit4ClassRunner.class)
  2. @ContextConfiguration(locations = { "classpath:cache.xml" })
  3. public class CacheTester {
  4. ?? ?@Test public void cacheAnnotation() {
  5. ?? ??? ?this.map("a");
  6. ?? ??? ?this.map("a");
  7. ?? ?}
  8. ?? ?@Cacheable(value="passwordRetryCache",key="#key")
  9. ?? ?public String map(String key) {
  10. ?? ??? ?System.out.println("get value for key: "+key);
  11. ?? ??? ?return "value: "+key;
  12. ?? ?}
  13. }

或者再换一种方式:手动使用代理方式调用同类方法也是可以的

  1. public class CacheBean {
  2. ?? ?@Autowired ApplicationContext applicationContext;
  3. ?? ?@Cacheable(value="passwordRetryCache",key="#key")
  4. ?? ?public String map(String key) { ?//方法不能为private,否则也没有缓存效果
  5. ?? ??? ?System.out.println("get value for key: "+key);
  6. ?? ??? ?return "value: "+key;
  7. ?? ?}
  8. ?? ?public String map2(String key) {
  9. ?? ??? ?CacheBean proxy = applicationContext.getBean(CacheBean.class);
  10. ?? ??? ?return proxy.map(key); //这里使用proxy调用map就可以缓存,而直接调用map则没有缓存
  11. ?? ?}
  12. }

以上为个人经验,希望能给大家一个参考,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号