2017-09-01 97 views
2

我有一個問題,實施一個二流緩存管理器。目前我正在使用EhCache,它工作正常。另外我想實現Java簡單緩存。春季:多個高速緩存管理器

我CacheConfiguration看起來是這樣的:

CacheConfiguration.java

@Configuration 
@EnableCaching 
@AutoConfigureAfter(value = { MetricsConfiguration.class }) 
@AutoConfigureBefore(value = { WebConfigurer.class, DatabaseConfiguration.class }) 
public class CacheConfiguration { 

private final javax.cache.configuration.Configuration<Object, Object> jcacheConfiguration; 

public CacheConfiguration(JHipsterProperties jHipsterProperties) { 
    JHipsterProperties.Cache.Ehcache ehcache = 
     jHipsterProperties.getCache().getEhcache(); 

    jcacheConfiguration = Eh107Configuration.fromEhcacheCacheConfiguration(
     CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class, 
      ResourcePoolsBuilder.heap(ehcache.getMaxEntries())) 
      .withExpiry(Expirations.timeToLiveExpiration(Duration.of(ehcache.getTimeToLiveSeconds(), TimeUnit.SECONDS))) 
      .build()); 
} 

/** 
* EhCache configuration 
* 
* @return 
*/ 
@Bean 
@Primary 
public JCacheManagerCustomizer cacheManagerCustomizer() { 
    return cm -> {   
     cm.createCache(com.david.coinlender.domain.News.class.getName(), jcacheConfiguration); 

// ...More caches 
} 

/** 
* Java Simple Cache configuration 
* @return 
*/ 
@Bean 
@Qualifier("simpleCacheManager") 
public CacheManager simpleCacheManager() { 

    SimpleCacheManager simpleCacheManager = new SimpleCacheManager();  
    simpleCacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("bitfinexAuthCache"))); 

    return simpleCacheManager; 

} 

}

用簡單的緩存我想緩存的對象。即:

@Cacheable(cacheManager = "simpleCacheManager", cacheNames = "bitfinexAuthCache", key = "#apiKey.apiKey") 
private Exchange createBitfinexAuthenticatedExchange(ApiKeys apiKey) { 

    ExchangeSpecification exSpec = new BitfinexExchange().getDefaultExchangeSpecification(); 
    exSpec.setApiKey(apiKey.getApiKey()); 
    exSpec.setSecretKey(apiKey.getSecret()); 

    Exchange bfx = ExchangeFactory.INSTANCE.createExchange(BitfinexExchange.class.getName()); 
    bfx.applySpecification(exSpec); 

    return bfx; 
} 

然而,在服務器啓動時liquibase給我一個錯誤,指出:

Caused by: java.lang.IllegalStateException: All Hibernate caches should be created upfront. Please update CacheConfiguration.java to add com.david.coinlender.domain.News 
at io.github.jhipster.config.jcache.NoDefaultJCacheRegionFactory.createCache(NoDefaultJCacheRegionFactory.java:37) 
at org.hibernate.cache.jcache.JCacheRegionFactory.getOrCreateCache(JCacheRegionFactory.java:190) 
at org.hibernate.cache.jcache.JCacheRegionFactory.buildEntityRegion(JCacheRegionFactory.java:113) 
at org.hibernate.cache.spi.RegionFactory.buildEntityRegion(RegionFactory.java:132) 
at org.hibernate.internal.CacheImpl.determineEntityRegionAccessStrategy(CacheImpl.java:439) 
at org.hibernate.metamodel.internal.MetamodelImpl.initialize(MetamodelImpl.java:120) 
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:297) 
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:445) 
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:889) 
... 25 common frames omitted 

我用我的器件的應用框架Jhipster。我現在將這個問題搜索了幾個小時,還沒有找到解決方案。

由於配置錯誤導致此錯誤?有人可以請指點我正確的方向嗎?

+0

嘗試'@Bean( 「simpleCacheManager」)'代替'@ Qualifier' –

+0

不幸的是拋出了同樣的錯誤:/ – dave0688

回答

3

在JHipster中(我做了代碼),實際上有兩層緩存。你有Spring Cache和Hibernate Second Level Cache。兩者都使用相同的實際Ehcache CacheManager

就你而言,你已經用Spring的簡單緩存替換了Ehcache。但由於NoDefaultJCacheRegionFactory仍然在Hibernate上配置,它仍然是用於Hibernate的Ehcache。但定製器不再使用。所以它失敗了。

您希望爲Spring和Ehcache for Hibernate創建一個簡單的緩存。這意味着實際上並不需要在Spring中爲Ehcache註冊bean。

最簡單的是,然後執行以下操作。

首先,在DatabaseConfiguration配置Ehcache。因此,當休眠JCache工廠將檢索它時,它將被正確配置。

public DatabaseConfiguration(Environment env, JHipsterProperties jHipsterProperties) { 
    this.env = env; 

    JHipsterProperties.Cache.Ehcache ehcache = 
     jHipsterProperties.getCache().getEhcache(); 

    CachingProvider provider = Caching.getCachingProvider(); 
    javax.cache.CacheManager cacheManager = provider.getCacheManager(); 

    javax.cache.configuration.Configuration<Object, Object> jcacheConfiguration = Eh107Configuration.fromEhcacheCacheConfiguration(
     CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class, 
      ResourcePoolsBuilder.heap(ehcache.getMaxEntries())) 
      .withExpiry(Expirations.timeToLiveExpiration(Duration.of(ehcache.getTimeToLiveSeconds(), TimeUnit.SECONDS))) 
      .build()); 

    cacheManager.createCache(com.mycompany.myapp.domain.User.class.getName(), jcacheConfiguration); 
    cacheManager.createCache(com.mycompany.myapp.domain.Authority.class.getName(), jcacheConfiguration); 
    cacheManager.createCache(com.mycompany.myapp.domain.User.class.getName() + ".authorities", jcacheConfiguration); 
} 

然後,配置Spring Cache。

public class CacheConfiguration { 

    public CacheConfiguration() { 
    } 

    @Bean 
    public CacheManager cacheManager() { 
     SimpleCacheManager cacheManager = new SimpleCacheManager(); 
     Collection<Cache> caches = Arrays.asList(
      new ConcurrentMapCache("mycache") 
      // ... 
     ); 
     cacheManager.setCaches(caches); 
     return cacheManager; 
    } 
} 
+0

感謝您的幫助。我發現這比我想象的要複雜得多。我會在接下來的幾天嘗試@Daniel C的建議並給你反饋。 – dave0688

+0

我其實想要實現兩個緩存管理器。對於「標準」hibernate二級緩存,我想使用EhCache(標記爲@Primary)。但是對於一些用例,我需要Java Simple Cache的實現(對於實例,我想緩存從API返回的對象 - 一種連接/交換對象)。 所以據我所知,僅在CacheConfiguration.java中實現第二個緩存是不可能的? – dave0688

+0

啊!這是不同的。這意味着你不需要從Spring發佈Ehcache。只需要配置提供者。然後公開簡單的緩存。讓我更新我的答案。 – Henri

1

@EnableCaching Doc

對於那些希望建立@EnableCaching和準確的高速緩存管理器bean之間更直接的關係被使用時,CachingConfigurer回調接口可以實現。請注意下面的@覆蓋標註方法:

有使用CachingConfigurer,並採取即在JCacheCacheConfiguration實施辦法另外的選擇。

1-實現CacheConfiguration類中的CachingConfigurer接口。一種選擇從JCacheConfigurerSupport延伸。

public class CustomCacheConfiguration extends JCacheConfigurerSupport { 

2-創建默認cacheManager豆,由於豆通過CachingConfigurer配置將被檢索爲默認cacheManager並且在這種情況下,它可以通過冬眠第二級高速緩存被用於該方法中,將cacheManagerCustomizer只是一種方法。像這樣:

@Bean 
    @Override 
    public CacheManager cacheManager() { 
     javax.cache.CacheManager jCacheCacheManager = createCacheManager(); 
     cacheManagerCustomizer().customize(jCacheCacheManager); 
     return new JCacheCacheManager(jCacheCacheManager); 
    } 

    private javax.cache.CacheManager createCacheManager() { 
     CachingProvider cachingProvider = Caching.getCachingProvider(); 
     return cachingProvider.getCacheManager(); 
    } 

    private JCacheManagerCustomizer cacheManagerCustomizer() { 
     return cm -> { 

      cm.createCache(org.demo.app.domain.User.class.getName(), jcacheConfiguration); 
     ...... 

     }; 
} 

3-創建simpleCacheManager

@Bean("simpleCacheManager") 
    public SimpleCacheManager simpleCacheManager() { 
     SimpleCacheManager simpleCacheManager = new SimpleCacheManager(); 
     simpleCacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("bitfinexAuthCache"))); 

     return simpleCacheManager; 

    } 
  • 爲了定義哪些cacheManager將用於隨後通過@Cacheable(cacheManager = "simpleCacheManager", cacheNames = "bitfinexAuthCache")
  • 定義它

    這裏是完整的定製CacheConfiguration

    @Configuration 
    @EnableCaching 
    @AutoConfigureAfter(value = { MetricsConfiguration.class }) 
    @AutoConfigureBefore(value = { WebConfigurer.class, DatabaseConfiguration.class}) 
    public class CacheConfiguration extends JCacheConfigurerSupport { 
    
        private final javax.cache.configuration.Configuration<Object, Object> jcacheConfiguration; 
    
    
        public CustomCacheConfiguration(JHipsterProperties jHipsterProperties) { 
         JHipsterProperties.Cache.Ehcache ehcache = 
          jHipsterProperties.getCache().getEhcache(); 
    
    
    
    
         jcacheConfiguration = Eh107Configuration.fromEhcacheCacheConfiguration(
          CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class, 
           ResourcePoolsBuilder.heap(ehcache.getMaxEntries())) 
           .withExpiry(Expirations.timeToLiveExpiration(Duration.of(ehcache.getTimeToLiveSeconds(), TimeUnit.SECONDS))) 
           .build()); 
        } 
    
    
        @Bean 
        @Override 
        public CacheManager cacheManager() { 
         javax.cache.CacheManager jCacheCacheManager = createCacheManager(); 
         cacheManagerCustomizer().customize(jCacheCacheManager); 
         return new JCacheCacheManager(jCacheCacheManager); 
        } 
    
        private javax.cache.CacheManager createCacheManager() { 
         CachingProvider cachingProvider = Caching.getCachingProvider(); 
         return cachingProvider.getCacheManager(); 
        } 
    
    
        private JCacheManagerCustomizer cacheManagerCustomizer() { 
         return cm -> { 
    
          cm.createCache(org.demo.app.domain.User.class.getName(), jcacheConfiguration); 
          cm.createCache(org.demo.app.domain.Authority.class.getName(), jcacheConfiguration); 
          cm.createCache(org.demo.app.domain.User.class.getName() + ".authorities", jcacheConfiguration); 
          cm.createCache(org.demo.app.domain.Company.class.getName(), jcacheConfiguration); 
          //cm.createCache(org.demo.app.domain.News.class.getName(), jcacheConfiguration); 
    
         }; 
        } 
    
        @Bean("simpleCacheManager") 
        public SimpleCacheManager simpleCacheManager() { 
         SimpleCacheManager simpleCacheManager = new SimpleCacheManager(); 
         simpleCacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("bitfinexAuthCache"))); 
    
         return simpleCacheManager; 
    
        } 
    
    } 
    
    +0

    號的'NoDefaultJCacheRegionFactory'擴展'JCacheRegionFactory'。做你說的會有用,但你不會得到你想的緩存。 – Henri

    +0

    你是對的!!''simpleCacheManager'覆蓋了默認的'jCacheCacheManager',只要我創建'simpleCacheManager' bean,默認的緩存管理器就消失了。我錯了,謝謝你的評論。我會再試一次。 –

    +0

    嗨@亨利,我添加了一個基於'CachingConfigurer'接口的新選擇。 –