Merge branch '1.5.x'
This commit is contained in:
@@ -16,9 +16,12 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.cache;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
@@ -67,11 +70,18 @@ import org.springframework.util.Assert;
|
||||
@AutoConfigureBefore(HibernateJpaAutoConfiguration.class)
|
||||
@AutoConfigureAfter({ CouchbaseAutoConfiguration.class, HazelcastAutoConfiguration.class,
|
||||
RedisAutoConfiguration.class })
|
||||
@Import({ CacheManagerCustomizers.class, CacheConfigurationImportSelector.class })
|
||||
@Import(CacheConfigurationImportSelector.class)
|
||||
public class CacheAutoConfiguration {
|
||||
|
||||
static final String VALIDATOR_BEAN_NAME = "cacheAutoConfigurationValidator";
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public CacheManagerCustomizers cacheManagerCustomizers(
|
||||
ObjectProvider<List<CacheManagerCustomizer<?>>> customizers) {
|
||||
return new CacheManagerCustomizers(customizers.getIfAvailable());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public static CacheManagerValidatorPostProcessor cacheAutoConfigurationValidatorPostProcessor() {
|
||||
|
||||
@@ -17,28 +17,34 @@
|
||||
package org.springframework.boot.autoconfigure.cache;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.ResolvableType;
|
||||
|
||||
/**
|
||||
* Invokes the available {@link CacheManagerCustomizer} instances in the context for a
|
||||
* given {@link CacheManager}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.5.0
|
||||
*/
|
||||
class CacheManagerCustomizers implements ApplicationContextAware {
|
||||
public class CacheManagerCustomizers {
|
||||
|
||||
private ConfigurableApplicationContext applicationContext;
|
||||
private static final Log logger = LogFactory.getLog(CacheManagerCustomizers.class);
|
||||
|
||||
private final List<CacheManagerCustomizer<?>> customizers;
|
||||
|
||||
public CacheManagerCustomizers(
|
||||
List<? extends CacheManagerCustomizer<?>> customizers) {
|
||||
this.customizers = (customizers != null ?
|
||||
new ArrayList<CacheManagerCustomizer<?>>(customizers) :
|
||||
Collections.<CacheManagerCustomizer<?>>emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Customize the specified {@link CacheManager}. Locates all
|
||||
@@ -49,49 +55,31 @@ class CacheManagerCustomizers implements ApplicationContextAware {
|
||||
* @return the cache manager
|
||||
*/
|
||||
public <T extends CacheManager> T customize(T cacheManager) {
|
||||
List<CacheManagerCustomizer<CacheManager>> customizers = findCustomizers(
|
||||
cacheManager);
|
||||
AnnotationAwareOrderComparator.sort(customizers);
|
||||
for (CacheManagerCustomizer<CacheManager> customizer : customizers) {
|
||||
customizer.customize(cacheManager);
|
||||
for (CacheManagerCustomizer<?> customizer : this.customizers) {
|
||||
Class<?> generic = ResolvableType
|
||||
.forClass(CacheManagerCustomizer.class,
|
||||
customizer.getClass())
|
||||
.resolveGeneric();
|
||||
if (generic.isInstance(cacheManager)) {
|
||||
customize(cacheManager, customizer);
|
||||
}
|
||||
}
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private List<CacheManagerCustomizer<CacheManager>> findCustomizers(
|
||||
CacheManager cacheManager) {
|
||||
if (this.applicationContext == null) {
|
||||
return Collections.emptyList();
|
||||
private void customize(CacheManager cacheManager, CacheManagerCustomizer customizer) {
|
||||
try {
|
||||
customizer.customize(cacheManager);
|
||||
}
|
||||
Class<?> cacheManagerClass = cacheManager.getClass();
|
||||
List<CacheManagerCustomizer<CacheManager>> customizers = new ArrayList<CacheManagerCustomizer<CacheManager>>();
|
||||
for (CacheManagerCustomizer customizer : getBeans(CacheManagerCustomizer.class)) {
|
||||
if (canCustomize(customizer, cacheManagerClass)) {
|
||||
customizers.add(customizer);
|
||||
catch (ClassCastException ex) {
|
||||
// Possibly a lambda-defined listener which we could not resolve the generic
|
||||
// event type for
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Non-matching transaction manager type for customizer: "
|
||||
+ customizer, ex);
|
||||
}
|
||||
}
|
||||
return customizers;
|
||||
}
|
||||
|
||||
private <T> Collection<T> getBeans(Class<T> type) {
|
||||
return BeanFactoryUtils.beansOfTypeIncludingAncestors(
|
||||
this.applicationContext.getBeanFactory(), type).values();
|
||||
}
|
||||
|
||||
private boolean canCustomize(CacheManagerCustomizer<?> customizer,
|
||||
Class<?> cacheManagerClass) {
|
||||
Class<?> target = GenericTypeResolver.resolveTypeArgument(customizer.getClass(),
|
||||
CacheManagerCustomizer.class);
|
||||
return (target == null || target.isAssignableFrom(cacheManagerClass));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
if (applicationContext instanceof ConfigurableApplicationContext) {
|
||||
this.applicationContext = (ConfigurableApplicationContext) applicationContext;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,80 +16,86 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.cache;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.test.util.EnvironmentTestUtils;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.caffeine.CaffeineCacheManager;
|
||||
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
|
||||
/**
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class CacheManagerCustomizersTests {
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
@Test
|
||||
public void customizeWithNullCustomizersShouldDoNothing() {
|
||||
new CacheManagerCustomizers(null)
|
||||
.customize(mock(CacheManager.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customizeSimpleCacheManager() {
|
||||
load(SimpleConfiguration.class, "spring.cache.type=simple");
|
||||
ConcurrentMapCacheManager cacheManager = this.context
|
||||
.getBean(ConcurrentMapCacheManager.class);
|
||||
CacheManagerCustomizers customizers = new CacheManagerCustomizers(
|
||||
Collections.singletonList(new CacheNamesCacheManagerCustomizer()));
|
||||
ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
|
||||
customizers.customize(cacheManager);
|
||||
assertThat(cacheManager.getCacheNames()).containsOnly("one", "two");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customizeNoConfigurableApplicationContext() {
|
||||
CacheManagerCustomizers invoker = new CacheManagerCustomizers();
|
||||
ApplicationContext context = mock(ApplicationContext.class);
|
||||
invoker.setApplicationContext(context);
|
||||
invoker.customize(mock(CacheManager.class));
|
||||
verifyZeroInteractions(context);
|
||||
public void customizeShouldCheckGeneric() throws Exception {
|
||||
List<TestCustomizer<?>> list = new ArrayList<TestCustomizer<?>>();
|
||||
list.add(new TestCustomizer<CacheManager>());
|
||||
list.add(new TestConcurrentMapCacheManagerCustomizer());
|
||||
CacheManagerCustomizers customizers = new CacheManagerCustomizers(list);
|
||||
customizers.customize(mock(CacheManager.class));
|
||||
assertThat(list.get(0).getCount()).isEqualTo(1);
|
||||
assertThat(list.get(1).getCount()).isEqualTo(0);
|
||||
customizers.customize(mock(ConcurrentMapCacheManager.class));
|
||||
assertThat(list.get(0).getCount()).isEqualTo(2);
|
||||
assertThat(list.get(1).getCount()).isEqualTo(1);
|
||||
customizers.customize(mock(CaffeineCacheManager.class));
|
||||
assertThat(list.get(0).getCount()).isEqualTo(3);
|
||||
assertThat(list.get(1).getCount()).isEqualTo(1);
|
||||
}
|
||||
|
||||
private void load(Class<?> config, String... environment) {
|
||||
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
|
||||
EnvironmentTestUtils.addEnvironment(applicationContext, environment);
|
||||
applicationContext.register(config);
|
||||
applicationContext.register(CacheAutoConfiguration.class);
|
||||
applicationContext.refresh();
|
||||
this.context = applicationContext;
|
||||
}
|
||||
static class CacheNamesCacheManagerCustomizer
|
||||
implements CacheManagerCustomizer<ConcurrentMapCacheManager> {
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class SimpleConfiguration {
|
||||
|
||||
@Bean
|
||||
public CacheManagerCustomizer<ConcurrentMapCacheManager> cacheManagerCustomizer() {
|
||||
return new CacheManagerCustomizer<ConcurrentMapCacheManager>() {
|
||||
|
||||
@Override
|
||||
public void customize(ConcurrentMapCacheManager cacheManager) {
|
||||
cacheManager.setCacheNames(Arrays.asList("one", "two"));
|
||||
}
|
||||
|
||||
};
|
||||
@Override
|
||||
public void customize(ConcurrentMapCacheManager cacheManager) {
|
||||
cacheManager.setCacheNames(Arrays.asList("one", "two"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class TestCustomizer<T extends CacheManager>
|
||||
implements CacheManagerCustomizer<T> {
|
||||
|
||||
private int count;
|
||||
|
||||
@Override
|
||||
public void customize(T cacheManager) {
|
||||
this.count++;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return this.count;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class TestConcurrentMapCacheManagerCustomizer
|
||||
extends TestCustomizer<ConcurrentMapCacheManager> {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user