spring cache CacheException: Another unnamed CacheManager already exists in the same VM. Please

springboot1.x系列中,spring-boot-starter-data-redis包客戶端使用的是jedis,但是到了springboot2.x其中使用的是Lettuce。 

用redis做緩存時,有以下兩種方式:

①與spring-cache集成,查詢時緩存,增刪改時刪除緩存

②寫個redis工具類,自己在需要的地方寫插入和查詢的方法

 

可以同時使用ehcache做系統緩存和hibernate的二級緩存

spring:
  jpa:
    properties:
      hibernate:
        cache:
          # 二級緩存 針對實體的
          use_second_level_cache: true
          provider_configuration_file_resource_path: ehcache-hibernate.xml
          region:
            factory_class: org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
  cache:
    type: ehcache
    ehcache:
      config: classpath:ehcache-spring.xml

問題是我想同時用redis和ehcache 和spring-cache集成做系統緩存,同時又用ehcache做hibernate的二級緩存,

這就尷尬了。

①yml中配置系統ehcache,java config 配置redisCache,redis會覆蓋掉ehcache,如下源碼。

@Configuration
@ConditionalOnClass({CacheManager.class})
@ConditionalOnBean({CacheAspectSupport.class})
@ConditionalOnMissingBean(
    value = {CacheManager.class},
    name = {"cacheResolver"}
)
@EnableConfigurationProperties({CacheProperties.class})
@AutoConfigureAfter({CouchbaseAutoConfiguration.class, HazelcastAutoConfiguration.class, HibernateJpaAutoConfiguration.class, RedisAutoConfiguration.class})
@Import({CacheAutoConfiguration.CacheConfigurationImportSelector.class})
public class CacheAutoConfiguration {
    public CacheAutoConfiguration() {
    }

②java config 配置ehcache和redisCache,會報錯,已經有了hibernate二級緩存的cachemanager了。

    @Bean(name = "redisCacheManager")
    //@Primary
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration difConf = getDefConf().entryTtl(Duration.ofHours(1));

        //自定義的緩存過期時間配置
        int configSize = cacheManagerProperties.getConfigs() == null ? 0 : cacheManagerProperties.getConfigs().size();
        Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>(configSize);
        if (configSize > 0) {
            cacheManagerProperties.getConfigs().forEach(e -> {
                RedisCacheConfiguration conf = getDefConf().entryTtl(Duration.ofSeconds(e.getSecond()));
                redisCacheConfigurationMap.put(e.getKey(), conf);
            });
        }

        return RedisCacheManager.builder(redisConnectionFactory)
                .cacheDefaults(difConf)
                .withInitialCacheConfigurations(redisCacheConfigurationMap)
                .build();
    }
    @Bean(name="ehCacheManagerFactoryBean")
    public EhCacheManagerFactoryBean ehCache (){
        EhCacheManagerFactoryBean factory = new EhCacheManagerFactoryBean();
        factory.setConfigLocation(new ClassPathResource("ehcache-spring.xml"));
        return factory;
    }

    @Bean
    public CacheManager cacheManager(net.sf.ehcache.CacheManager cacheManager){
        return new EhCacheCacheManager(cacheManager);
    }
2019-01-31 17:49:15.828  WARN 21516 --- [main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ehCache' defined in class path resource [com/ccm/yundu/bi/core/config/CacheConfig.class]: Invocation of init method failed; nested exception is net.sf.ehcache.CacheException: Another unnamed CacheManager already exists in the same VM. Please provide unique names for each CacheManager in the config or do one of following:
1. Use one of the CacheManager.create() static factory methods to reuse same CacheManager with same name or create one if necessary
2. Shutdown the earlier cacheManager before creating new one with same name.

 net.sf.ehcache.CacheManager默認是單例的,如下。

public static CacheManager create(Configuration config) throws CacheException {
        if (singleton != null) {
            LOG.debug("Attempting to create an existing singleton. Existing singleton returned.");
            return singleton;
        } else {
            Class var1 = CacheManager.class;
            synchronized(CacheManager.class) {
                if (singleton == null) {
                    singleton = newInstance(config);
                } else {
                    LOG.debug("Attempting to create an existing singleton. Existing singleton returned.");
                }

                return singleton;
            }
        }
    }

最後用的別的方法生成net.sf.ehcache.CacheManager,然後就OK了。


    @Bean(name="ehCacheManager")
    @Primary
    public CacheManager cacheManager(){
        URL url = getClass().getResource("/ehcache-spring.xml");
        net.sf.ehcache.CacheManager manager=net.sf.ehcache.CacheManager.newInstance(url);
        /*EhCacheManagerFactoryBean factory = new EhCacheManagerFactoryBean();
        factory.setConfigLocation(new ClassPathResource("ehcache-spring.xml"));*/
        return new EhCacheCacheManager(manager);
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章