Java 自定义缓存解析程序不工作

Java 自定义缓存解析程序不工作,java,spring,spring-cache,Java,Spring,Spring Cache,我有一个Spring Boot项目,其中有一个自定义的CacheResolver,因为我需要在运行时决定要使用哪个缓存,我没有任何编译错误,但是,当我做一些测试并在自定义的CacheResolver上放置断点时,它永远不会进入其中 这是我的缓存配置类: @Configuration @EnableCaching(proxyTargetClass = true) @PropertySource(CacheConfig.CLASSPATH_DEPLOY_CACHE_PROPERTIES_PROPER

我有一个Spring Boot项目,其中有一个自定义的
CacheResolver
,因为我需要在运行时决定要使用哪个缓存,我没有任何编译错误,但是,当我做一些测试并在自定义的
CacheResolver
上放置断点时,它永远不会进入其中

这是我的缓存配置类:

@Configuration
@EnableCaching(proxyTargetClass = true)
@PropertySource(CacheConfig.CLASSPATH_DEPLOY_CACHE_PROPERTIES_PROPERTIES)
public class CacheConfig extends CachingConfigurerSupport{

      public static final String CLASSPATH_DEPLOY_CACHE_PROPERTIES_PROPERTIES = "classpath:/deploy/cache-properties.properties";

      public static final String CACHEABLE_DOCUMENTS_PROPERTY = "cacheable.documents";
      public static final String TTL_CACHEABLE_DOCUMENTS_PROPERTY = "ttl.cacheable.documents";
      public static final String SIZED_CACHEABLE_DOCUMENTS_PROPERTY = "sized.cacheable.documents";
      public static final String CACHE_NAME = "permanentCache";
      public static final String TTL_CACHE = "ttlCache";
      public static final String SIZED_CACHE = "sizedCache";
      public static final String CACHEABLE_DOCUMENTS = "cacheableDocuments";
      public static final String SIZED_CACHEABLE_DOCUMENTS = "sizedCacheableDocuments";
      public static final int WEIGHT = 1000000;
      public static final int TO_KBYTES = 1000;

      @Inject
      protected Environment environment;

      //@Bean
      @Override
      public CacheManager cacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        GuavaCache sizedCache = new GuavaCache(SIZED_CACHE, CacheBuilder.newBuilder().maximumWeight(WEIGHT).weigher(
                (key, storable) -> {
                  String json = ((Storable) storable).toJson();
                  return json.getBytes().length / TO_KBYTES;
                }
        ).build());
        GuavaCache permanentCache = new GuavaCache(CACHE_NAME,CacheBuilder.newBuilder().build());
        //GuavaCache ttlCache = new GuavaCache(TTL_CACHE, CacheBuilder.newBuilder().expireAfterWrite(30, TimeUnit.MINUTES).build());
        cacheManager.setCaches(Arrays.asList(permanentCache,sizedCache));
        return cacheManager;
      }

      @Bean(name = "wgstCacheResolver")
      @Override
      public CacheResolver cacheResolver(){
        CacheResolver cacheResolver = new WgstCacheResolver(cacheManager(),cacheableDocuments(),sizedCacheableDocuments());
        return cacheResolver;
      }


      @Bean(name = CACHEABLE_DOCUMENTS)
      public List<String> cacheableDocuments(){
        String[] cacheableDocuments = StringUtils.commaDelimitedListToStringArray(environment.getProperty(CACHEABLE_DOCUMENTS_PROPERTY));
        return Arrays.asList(cacheableDocuments);
      }

      @Bean(name = SIZED_CACHEABLE_DOCUMENTS)
      public List<String> sizedCacheableDocuments(){
        String[] sizedCacheableDocuments = StringUtils.commaDelimitedListToStringArray(environment.getProperty(SIZED_CACHEABLE_DOCUMENTS_PROPERTY));
        return Arrays.asList(sizedCacheableDocuments);
      } 
    }
@配置
@EnableCaching(proxyTargetClass=true)
@PropertySource(CacheConfig.CLASSPATH\u DEPLOY\u CACHE\u PROPERTIES\u PROPERTIES)
公共类CacheConfig扩展了CachingConfigurerSupport{
公共静态最终字符串CLASSPATH\u DEPLOY\u CACHE\u PROPERTIES\u PROPERTIES=“CLASSPATH:/DEPLOY/CACHE PROPERTIES.PROPERTIES”;
公共静态最终字符串CACHEABLE\u DOCUMENTS\u PROPERTY=“CACHEABLE.DOCUMENTS”;
公共静态最终字符串TTL\u CACHEABLE\u DOCUMENTS\u PROPERTY=“TTL.CACHEABLE.DOCUMENTS”;
公共静态最终字符串大小\u可缓存\u文档\u PROPERTY=“size.CACHEABLE.DOCUMENTS”;
公共静态最终字符串缓存\u NAME=“permanentCache”;
公共静态最终字符串TTL_CACHE=“ttlCache”;
公共静态最终字符串大小_CACHE=“sizedCache”;
公共静态最终字符串CACHEABLE_DOCUMENTS=“cacheableDocuments”;
公共静态最终字符串大小的可缓存文档=“SizedCachableDocuments”;
公共静态最终整数权重=1000000;
公共静态最终整数到千字节=1000;
@注入
保护环境;
//@豆子
@凌驾
公共缓存管理器缓存管理器(){
SimpleCacheManager cacheManager=新的SimpleCacheManager();
GuavaCache sizedCache=新的GuavaCache(SIZED_CACHE,CacheBuilder.newBuilder()。最大重量(重量)。称重器(
(键,可存储)->{
字符串json=((可存储)可存储).toJson();
将json.getBytes().length/返回到_KBYTES;
}
).build());
GuavaCache permanentCache=新的GuavaCache(CACHE_NAME,CacheBuilder.newBuilder().build());
//GuavaCache ttlCache=新的Guavache(TTL_缓存,CacheBuilder.newBuilder().expireAfterWrite(30,TimeUnit.MINUTES).build());
setCaches(Arrays.asList(permanentCache,sizedCache));
返回缓存管理器;
}
@Bean(name=“wgstcachesolver”)
@凌驾
公共CacheResolver CacheResolver(){
CacheSolver CacheSolver=新的WGSTCacheSolver(cacheManager(),cacheableDocuments(),sizedCacheableDocuments());
返回高速缓存解析器;
}
@Bean(名称=可缓存的文档)
公共列表可缓存文档(){
String[]cacheableDocuments=StringUtils.CommadeLimitedListToStringAray(environment.getProperty(CACHEABLE_DOCUMENTS_PROPERTY));
返回数组.asList(可缓存文档);
}
@Bean(名称=大小可缓存文档)
公共列表大小可缓存文档(){
String[]sizedCacheableDocuments=StringUtils.CommadeLimitedListToStringAray(environment.getProperty(SIZED\u CACHEABLE\u DOCUMENTS\u PROPERTY));
返回数组.asList(sizedCacheableDocuments);
} 
}
这是我的缓存解析器

public class WgstCacheResolver extends AbstractCacheResolver {

  private final List<String> cacheableDocuments;
  private final List<String> sizedCacheableDocuments;

  public WgstCacheResolver(final CacheManager cacheManager,final List<String> cacheableDocuments, final List<String> sizedCacheableDocuments) {
    super(cacheManager);
    this.cacheableDocuments = cacheableDocuments;
    this.sizedCacheableDocuments = sizedCacheableDocuments;
  }

  /**
   * Resolves the cache(s) to be updated on runtime
   * @param context
   * @return*/
  @Override
  protected Collection<String> getCacheNames(final CacheOperationInvocationContext<?> context) {

    final Collection<String> cacheNames = new ArrayList<>();
    final AbstractDao dao = (AbstractDao)context.getTarget();
    final String documentType = dao.getDocumentType().toString();
    if (cacheableDocuments.contains(documentType)){
      cacheNames.add("permanentCache");
    }
    if (sizedCacheableDocuments.contains(documentType)){
      cacheNames.add("sizedCache");
    }
    return cacheNames;
  }
}
公共类wgstcachesolver扩展了AbstractCacheSolver{
私人最终清单文件;
私人最终列表大小可缓存文件;
公共WgstCacheResolver(最终缓存管理器缓存管理器、最终列表可缓存文档、最终列表大小可缓存文档){
高级(缓存管理器);
this.cacheableDocuments=cacheableDocuments;
this.sizedCachableDocuments=sizedCachableDocuments;
}
/**
*解析要在运行时更新的缓存
*@param上下文
*@返回*/
@凌驾
受保护的集合getCacheNames(最终缓存操作上下文){
最终集合cacheNames=new ArrayList();
final AbstractDao=(AbstractDao)context.getTarget();
最后一个字符串documentType=dao.getDocumentType().toString();
if(cacheableDocuments.contains(documentType)){
cacheNames.add(“permanentCache”);
}
if(sizedCacheableDocuments.contains(documentType)){
添加(“sizedCache”);
}
返回缓存名称;
}
}
这里是我使用缓存的DAO:

    @Component
    @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.DEFAULT)
    @CacheConfig(cacheResolver = "wgstCacheResolver")
    public class CacheableDao<T extends Storable> extends AbstractDao<T> {

      private final Logger logger = LoggerFactory.getLogger(CacheableDao.class);

      public CacheableDao(final Bucket bucket, final Class<T> typeParameterClass, final DocumentType documentType) {
        super(bucket, typeParameterClass, documentType);
      }

      @Cacheable(key = "{#root.methodName, #root.target.generateFullKey(#key)}")
      public T get(final String key) throws DatastoreAccessException, ObjectMappingException {
        //do something
      }
.
.
.
}
@组件
@范围(值=ConfigurableBeanFactory.Scope\u原型,proxyMode=ScopedProxyMode.DEFAULT)
@CacheConfig(cacheResolver=“wgstcachesolver”)
公共类CacheableDao扩展了AbstractDao{
私有最终记录器Logger=LoggerFactory.getLogger(CacheableDao.class);
公共CacheableDao(最终存储桶、最终类类型ParameterClass、最终文档类型DocumentType){
超级(bucket、typeParameterClass、documentType);
}
@可缓存(key=“{#root.methodName,#root.target.generativelkey(#key)}”)
公共T get(最终字符串键)抛出DatastoreAccessException、ObjectMappingException{
//做点什么
}
.
.
.
}
我尝试过实现
CacheResolver
而不是扩展
AbstractCacheResolver
,但没有任何区别


谢谢。

缓存名称在某些时候需要包括在内,仅指定要使用的
缓存解析程序是不够的,
@Cacheable
类需要知道可用的缓存名称,因此我将它们包括在
@CacheConfig
注释中:

@CacheConfig(cacheNames = {WgstCacheConfig.PERMANENT_CACHE, WgstCacheConfig.SIZED_CACHE},
    cacheResolver = WgstCacheConfig.WGST_CACHE_RESOLVER)
public class CacheableDao<T extends Storable> extends AbstractDao<T> {
所以我把它放在这里,它很有效:

  @Bean
  public CacheManager cacheManager() {
    return null;
  }

  @Bean(name = WGST_CACHE_RESOLVER)
  public CacheResolver cacheResolver(){
    CacheResolver cacheResolver = new WgstCacheResolver(cacheableDocuments(),sizedCacheableDocuments(),getPermanentCache(),
                                                        getSizedCache());
    return cacheResolver;
  }
重新运行我的测试,单步执行我的自定义
CacheResolver
,它将按照预期的方式解析到正确的缓存


我的配置类不再扩展
CachingConfigurerSupport

经过一番反复(很抱歉!)之后,发现这确实是Spring框架中的一个bug


我创造了。期待下一个维护版本(
4.1.7.release
)的修复。感谢您的示例项目

您没有任何缓存名称,因此如果缓存有效,它必须解析缓存名称
  @Bean
  public CacheManager cacheManager() {
    return null;
  }

  @Bean(name = WGST_CACHE_RESOLVER)
  public CacheResolver cacheResolver(){
    CacheResolver cacheResolver = new WgstCacheResolver(cacheableDocuments(),sizedCacheableDocuments(),getPermanentCache(),
                                                        getSizedCache());
    return cacheResolver;
  }