Commit 1b3efd41 authored by Stephane Nicoll's avatar Stephane Nicoll

Expose caching-specific infrastructure

Expose the underlying cache infrastructure bean if Boot auto-configures
it. This is the case for ehCache, hazelcast and JCache. This change has
two side effects:

1. It is now possible to customize the underlying cache infrastructure
and let Boot only wrap it in the Spring's CacheManager abstraction. No
customizations are applied if the caching-specific service is customized
2. Such infrastructure is disposed when the application terminates as
it is now defined as `@Bean` and both `close()` and `shutdown()` methods
are invoked if present on the target type.

While the latter can be troublesome, we feel that a particular cache
instance is not meant to be shared and must be disposed when the
application terminates.

Closes gh-2848
parent b20d11fe
...@@ -17,11 +17,11 @@ ...@@ -17,11 +17,11 @@
package org.springframework.boot.autoconfigure.cache; package org.springframework.boot.autoconfigure.cache;
import net.sf.ehcache.Cache; import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cache.CacheManager;
import org.springframework.cache.ehcache.EhCacheCacheManager; import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.ehcache.EhCacheManagerUtils; import org.springframework.cache.ehcache.EhCacheManagerUtils;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
...@@ -34,11 +34,12 @@ import org.springframework.core.io.Resource; ...@@ -34,11 +34,12 @@ import org.springframework.core.io.Resource;
* a default configuration file exists. * a default configuration file exists.
* *
* @author Eddú Meléndez * @author Eddú Meléndez
* @author Stephane Nicoll
* @since 1.3.0 * @since 1.3.0
*/ */
@Configuration @Configuration
@ConditionalOnClass({ Cache.class, EhCacheCacheManager.class }) @ConditionalOnClass({ Cache.class, EhCacheCacheManager.class })
@ConditionalOnMissingBean(CacheManager.class) @ConditionalOnMissingBean(org.springframework.cache.CacheManager.class)
@Conditional({ CacheCondition.class, @Conditional({ CacheCondition.class,
EhCacheCacheConfiguration.ConfigAvailableCondition.class }) EhCacheCacheConfiguration.ConfigAvailableCondition.class })
class EhCacheCacheConfiguration { class EhCacheCacheConfiguration {
...@@ -47,13 +48,18 @@ class EhCacheCacheConfiguration { ...@@ -47,13 +48,18 @@ class EhCacheCacheConfiguration {
private CacheProperties properties; private CacheProperties properties;
@Bean @Bean
public EhCacheCacheManager cacheManager() { public EhCacheCacheManager cacheManager(CacheManager ehCacheCacheManager) {
return new EhCacheCacheManager(ehCacheCacheManager);
}
@Bean
@ConditionalOnMissingBean
public CacheManager ehCacheCacheManager() {
Resource location = this.properties.resolveConfigLocation(); Resource location = this.properties.resolveConfigLocation();
if (location != null) { if (location != null) {
return new EhCacheCacheManager( return EhCacheManagerUtils.buildCacheManager(location);
EhCacheManagerUtils.buildCacheManager(location));
} }
return new EhCacheCacheManager(EhCacheManagerUtils.buildCacheManager()); return EhCacheManagerUtils.buildCacheManager();
} }
/** /**
......
...@@ -57,11 +57,13 @@ class HazelcastCacheConfiguration { ...@@ -57,11 +57,13 @@ class HazelcastCacheConfiguration {
private CacheProperties cacheProperties; private CacheProperties cacheProperties;
@Bean @Bean
public HazelcastCacheManager cacheManager() throws IOException { public HazelcastCacheManager cacheManager(HazelcastInstance hazelcastInstance) {
return new HazelcastCacheManager(createHazelcastInstance()); return new HazelcastCacheManager(hazelcastInstance);
} }
private HazelcastInstance createHazelcastInstance() throws IOException { @Bean
@ConditionalOnMissingBean
public HazelcastInstance hazelcastInstance() throws IOException {
Resource location = this.cacheProperties.resolveConfigLocation(); Resource location = this.cacheProperties.resolveConfigLocation();
if (location != null) { if (location != null) {
Config cfg = new XmlConfigBuilder(location.getURL()).build(); Config cfg = new XmlConfigBuilder(location.getURL()).build();
......
...@@ -27,9 +27,11 @@ import javax.cache.configuration.MutableConfiguration; ...@@ -27,9 +27,11 @@ import javax.cache.configuration.MutableConfiguration;
import javax.cache.spi.CachingProvider; import javax.cache.spi.CachingProvider;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome; import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition; import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.bind.RelaxedPropertyResolver; import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.cache.jcache.JCacheCacheManager; import org.springframework.cache.jcache.JCacheCacheManager;
...@@ -68,19 +70,13 @@ class JCacheCacheConfiguration { ...@@ -68,19 +70,13 @@ class JCacheCacheConfiguration {
private List<JCacheManagerCustomizer> cacheManagerCustomizers; private List<JCacheManagerCustomizer> cacheManagerCustomizers;
@Bean @Bean
public JCacheCacheManager cacheManager() throws IOException { public JCacheCacheManager cacheManager(CacheManager jCacheCacheManager) {
CacheManager cacheManager = createCacheManager(); return new JCacheCacheManager(jCacheCacheManager);
List<String> cacheNames = this.cacheProperties.getCacheNames();
if (!CollectionUtils.isEmpty(cacheNames)) {
for (String cacheName : cacheNames) {
cacheManager.createCache(cacheName, getDefaultCacheConfiguration());
}
}
customize(cacheManager);
return new JCacheCacheManager(cacheManager);
} }
private CacheManager createCacheManager() throws IOException { @Bean
@ConditionalOnMissingBean
public CacheManager jCacheCacheManager() throws IOException {
CachingProvider cachingProvider = getCachingProvider(this.cacheProperties CachingProvider cachingProvider = getCachingProvider(this.cacheProperties
.getJcache().getProvider()); .getJcache().getProvider());
Resource configLocation = this.cacheProperties.resolveConfigLocation(); Resource configLocation = this.cacheProperties.resolveConfigLocation();
...@@ -89,7 +85,15 @@ class JCacheCacheConfiguration { ...@@ -89,7 +85,15 @@ class JCacheCacheConfiguration {
cachingProvider.getDefaultClassLoader(), cachingProvider.getDefaultClassLoader(),
createCacheManagerProperties(configLocation)); createCacheManagerProperties(configLocation));
} }
return cachingProvider.getCacheManager(); CacheManager jCacheCacheManager = cachingProvider.getCacheManager();
List<String> cacheNames = this.cacheProperties.getCacheNames();
if (!CollectionUtils.isEmpty(cacheNames)) {
for (String cacheName : cacheNames) {
jCacheCacheManager.createCache(cacheName, getDefaultCacheConfiguration());
}
}
customize(jCacheCacheManager);
return jCacheCacheManager;
} }
private CachingProvider getCachingProvider(String cachingProviderFqn) { private CachingProvider getCachingProvider(String cachingProviderFqn) {
...@@ -125,12 +129,32 @@ class JCacheCacheConfiguration { ...@@ -125,12 +129,32 @@ class JCacheCacheConfiguration {
} }
/** /**
* Determines if JCache is available. This either kick in if a default * Determine if JCache is available. This either kick in if a provider is available
* as defined per {@link JCacheProviderAvailableCondition} or if a {@link CacheManager}
* has already been defined.
*/
@Order(Ordered.LOWEST_PRECEDENCE)
static class JCacheAvailableCondition extends AnyNestedCondition {
public JCacheAvailableCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@Conditional(JCacheProviderAvailableCondition.class)
static class JCacheProvider {}
@ConditionalOnSingleCandidate(CacheManager.class)
static class CustomJCacheCacheManager {}
}
/**
* Determine if a JCache provider is available. This either kick in if a default
* {@link CachingProvider} has been found or if the property referring to the provider * {@link CachingProvider} has been found or if the property referring to the provider
* to use has been set. * to use has been set.
*/ */
@Order(Ordered.LOWEST_PRECEDENCE) @Order(Ordered.LOWEST_PRECEDENCE)
static class JCacheAvailableCondition extends SpringBootCondition { static class JCacheProviderAvailableCondition extends SpringBootCondition {
@Override @Override
public ConditionOutcome getMatchOutcome(ConditionContext context, public ConditionOutcome getMatchOutcome(ConditionContext context,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment