Использование EhCache в Spring 4 без XML

Есть ли способ инициализировать EhCache без xml в Spring 4 или Spring Boot?

Я заметил, что Spring Boot 1.0.0.RC3 не имеет никаких зависимостей от ehcache, но в выпуске Spring 4.0GA упоминается, что улучшена поддержка EhCache. Также у Spring 3 был класс org.springframework.cache.ehcache.EhCacheCacheManager но это больше не является частью зависимостей.

Изменить: Spring 4 имеет поддержку EhCache. Вы должны добавить зависимость:

<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>

Edit2: я попробовал следующее, и я думаю, что я близко, но я получаю ошибку:

@Bean
@Override
public CacheManager cacheManager() {
    CacheConfiguration cacheConfiguration = new CacheConfiguration();
    cacheConfiguration.setName("primary");
    cacheConfiguration.setMemoryStoreEvictionPolicy("LRU");
    cacheConfiguration.setMaxEntriesLocalHeap(0);

    net.sf.ehcache.config.Configuration config = new net.sf.ehcache.config.Configuration();
    config.addCache(cacheConfiguration);

    net.sf.ehcache.CacheManager cacheManager = new net.sf.ehcache.CacheManager(config);
    cacheManager.setName("EhCache");

    return new EhCacheCacheManager(cacheManager);
}

@Bean
public EhCacheManagerFactoryBean factoryBean() {
    return new EhCacheManagerFactoryBean();
}

ошибка

Caused by: 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.
The source of the existing CacheManager is: [Programmatically configured]
    at net.sf.ehcache.CacheManager.assertNoCacheManagerExistsWithSameName(CacheManager.java:590)
    at net.sf.ehcache.CacheManager.init(CacheManager.java:384)
    at net.sf.ehcache.CacheManager.<init>(CacheManager.java:263)
    at org.springframework.cache.ehcache.EhCacheManagerFactoryBean.afterPropertiesSet(EhCacheManagerFactoryBean.java:166)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549)
    ... 15 more

2 ответа

Решение

Конфигурация EhCache без XML в Spring

@Configuration
@EnableCaching
public class CachingConfig implements CachingConfigurer {
    @Bean(destroyMethod="shutdown")
    public net.sf.ehcache.CacheManager ehCacheManager() {
        CacheConfiguration cacheConfiguration = new CacheConfiguration();
        cacheConfiguration.setName("myCacheName");
        cacheConfiguration.setMemoryStoreEvictionPolicy("LRU");
        cacheConfiguration.setMaxEntriesLocalHeap(1000);

        net.sf.ehcache.config.Configuration config = new net.sf.ehcache.config.Configuration();
        config.addCache(cacheConfiguration);

        return net.sf.ehcache.CacheManager.newInstance(config);
    }

    @Bean
    @Override
    public CacheManager cacheManager() {
        return new EhCacheCacheManager(ehCacheManager());
    }

    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return new SimpleKeyGenerator();
    }

    @Bean
    @Override
    public CacheResolver cacheResolver()    {
        return new SimpleCacheResolver();
    }

    @Bean
    @Override
    public CacheErrorHandler errorHandler() {
         return new SimpleCacheErrorHandler();
    }
}

В качестве альтернативы для тестирования вы можете использовать простой ConcurrentMapCache, работающий без XML, как показано ниже.

@Configuration
@EnableCaching
public class CachingConfig implements CachingConfigurer {
    @Bean
    @Override
    public CacheManager cacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();

        List<Cache> caches = new ArrayList<Cache>();
        caches.add(new ConcurrentMapCache("myCacheName"));
        cacheManager.setCaches(caches);

        return cacheManager;
    }

    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return new SimpleKeyGenerator();
    }

    @Bean
    @Override
    public CacheResolver cacheResolver()    {
        return new SimpleCacheResolver();
    }

    @Bean
    @Override
    public CacheErrorHandler errorHandler() {
         return new SimpleCacheErrorHandler();
    }
}

Редактировать: Обновлено, чтобы добавить метод выключения в основной кэш.Редактировать: Добавлена ​​конфигурация для обработчика ошибок и распознавателя кэша.

Я делаю это на двух уровнях абстракции: файл конфигурации для каждой технологии (Ehcache, Redis и т. Д.) И общий файл конфигурации.

Вот то, что для Ehcache (Redis был бы похож):

@Configuration
public class EhCacheConfiguration {

    @Bean
    public EhCacheCacheManager ehCacheCacheManager() {

        return new EhCacheCacheManager(ehCacheManagerFactoryBean().getObject());
    }


    @Bean
    public EhCacheManagerFactoryBean ehCacheManagerFactoryBean() {

        EhCacheManagerFactoryBean cacheManagerFactoryBean = new EhCacheManagerFactoryBean();

        cacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));
        cacheManagerFactoryBean.setShared(true);

        return cacheManagerFactoryBean;
    }
}

А вот общий (в комплекте с крючками Redis):

@Configuration
@EnableCaching
public class CachingConfiguration implements CachingConfigurer {

    @Qualifier("ehCacheCacheManager")
    @Autowired(required = false)
    private CacheManager ehCacheCacheManager;

    @Qualifier("redisCacheManager")
    @Autowired(required = false)
    private CacheManager redisCacheManager;


    @Bean
    @Override
    public CacheManager cacheManager() {

        List<CacheManager> cacheManagers = Lists.newArrayList();

        if (this.ehCacheCacheManager != null) {
            cacheManagers.add(this.ehCacheCacheManager);
        }

        if (this.redisCacheManager != null) {
            cacheManagers.add(this.redisCacheManager);
        }

        CompositeCacheManager cacheManager = new CompositeCacheManager();

        cacheManager.setCacheManagers(cacheManagers);
        cacheManager.setFallbackToNoOpCache(false);

        return cacheManager;
    }


    @Bean
    @Override
    public KeyGenerator keyGenerator() {

        return new DefaultKeyGenerator();
    }
}

Мы используем EhCache - RMI Replication в одном из наших проектов. Для этого у нас есть два экземпляра, и теперь мы хотим добавить больше экземпляров. Есть ли способ добавить больше экземпляров без изменения кода. Или любой другой фреймворк для этого.

Другие вопросы по тегам