【问题标题】:Why @Cacheable doesn't work after second time method invoked为什么@Cacheable 在第二次调用方法后不起作用
【发布时间】:2018-09-20 20:36:45
【问题描述】:

弄清楚 cacheable 对我不起作用,因为带有 @Cacheable 注释的方法在具有这种结构的类内部。 我有

public interface Filter<T> {
    List<T> filter(int limit);
} 

和一堆实现:

@Component
public class UpcomingFilter implements Filter<Entity> {

    @Cacheable(value = {"upcoming"})
    @Override
    public List<Entity> filter(int limit) {
       //retrieve from repository
    }
}

@Component
public class RecentlyAddedFilter implements Filter<Entity> {
@Cacheable(value = {"recentlyAdded"})
    @Override
    public List<Entity> filter(int limit) {
       //retrieve from repository
    }
}
//and 6 more implementations

为了优化这个过滤器的自动装配,我使用了 HashMap,我保存了这个过滤器:

@EnableAspectJAutoProxy
@ComponentScan
@Configuration
public class AppConfig {

    @Bean("filtersMap")
    public Map<String, Filter> filters() {
        Map<String, Filter> filtersMap = new HashMap<>();

        filtersMap.put("upcomingFilter", new UpcomingFilter(sessionRepository));
        filtersMap.put("recentlyAddedFilter", new RecentlyAddedFilter(entityRepository));
        //..another filters
        return filtersMap;
    }

    }

我在我的服务层中自动装配这张地图:

@Qualifier("filtersMap") Map<String, Filter> filterMap

缓存配置:

@EnableCaching
@Configuration
public class CacheConfiguration {
    @Bean
    public CacheManager cacheManager() {
        String[] cacheNames = new String[] {"upcoming", "recentlyAdded"};
        return new ConcurrentMapCacheManager(cacheNames);
    }

}

我在每个过滤方法中都做 sysout 并测量执行时间。 它表明每次都调用了可缓存的方法,并且没有使用缓存。 比我创建简单的类 MyFilter 而不实现 Filter 接口, 用 @Cacheable 注释它的方法,它就像一个魅力。 那么,对于实现Filter接口

的类,如何解决缓存不起作用的问题

【问题讨论】:

  • 不清楚你在哪里调用你的过滤方法。但是根据经验,当您从同一个类中调用带注释的方法时,它们不会应用注释。为什么?因为注解是作为代理类实现的,同一个类中的调用不会去代理,而是去实际的类。
  • 嗨 Nikolas :)) 由于您创建了一个 CacheManager bean,请尝试添加返回 CustomerDataService 的 bean。
  • 嗨 Nikolas :)) CustomerDataService 是什么?
  • 不要手动实例化 bean!您不会从 Spring 中获得任何好处。为每个实例创建@Bean 方法,然后将它们自动连接到您的filtersMap 方法中。或者,更好的是,只使用getBeansOfType 而不要自己构建Map
  • @BoristheSpider 与我提到的无关。如果您有带有方法 b 和 c 的类 A 用可缓存的方法和内部方法 b 注释,则您调用方法 c 它不会命中缓存。因为注释在内部工作的方式。

标签: spring spring-cache


【解决方案1】:

通过此链接找到解决方案Method annotated with @Cacheable not getting intercepted 并由 Nikolas 评论:

将具有@Cacheable注解的Service bean添加到缓存配置类:

@EnableCaching
@Configuration
public class CacheConfiguration {

    @Bean
    public CacheManager cacheManager() {
        String[] cacheNames = new String[] {"upcoming", "recentlyAdded"};
        return new ConcurrentMapCacheManager(cacheNames);
    }

    @Bean
    public PopularFilter popularFilter() {
        return new PopularFilter(myRepository);
    }

     @Bean("filtersMap")
public Map<String, Filter> filters() {
    Map<String, Filter> filtersMap = new HashMap<>();
    filtersMap.put("popularFilter", popularFilter());
    //...
    return filtersMap;
}

【讨论】:

  • 但是如何在这个方法中使用@CachePut 更新这个缓存:@CachePut(value={"upcoming", "popular", "recentlyAdded", "recommendations"}) public Entity addEntity(RequestDto dto, User user) {/*some code*/} Cahe 没有更新。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-30
  • 1970-01-01
  • 2015-03-28
  • 2015-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多