From 3e4e9c2b2c6f88403b1e2bc9032b1578a588bc43 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Tue, 29 Apr 2014 08:01:07 +0200 Subject: [PATCH] DATACMNS-492 - RepositoryConfigurationDelegate now expects an Environment. Added a constructor to RepositoryConfigurationDelegate that takes an additional Environment instance to make sure we can equip ClasspathScanningCandidateComponentProviders with Environments to make sure they only find components matching the environment. Retain the old constructor by defaulting to the Environment the ResourceLoader potentially contains or even a StandardEnvironment in worse cases. This is primarily to not break existing clients. Those should be upgraded to use the new constructor, of course. Needed to add an additional guard in BeanDefinitionRegistrarSupport as Spring 3.2.8 fails to invoke EnvironmentAware (filed SPR-11744 for that). This should be removed once we upgrade to Spring 3.2.9. Related pull request: #80. Related tickets: DATACMNS-493, DATACMNS-494, SPR-11744. --- .../RepositoryBeanDefinitionBuilder.java | 11 ++++- .../RepositoryBeanDefinitionParser.java | 3 +- ...ositoryBeanDefinitionRegistrarSupport.java | 25 ++++++++++- .../RepositoryConfigurationDelegate.java | 41 ++++++++++++++++++- .../RepositoryConfigurationSourceSupport.java | 7 +++- ...itionRegistrarSupportIntegrationTests.java | 31 +++++++++++--- 6 files changed, 106 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionBuilder.java b/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionBuilder.java index 9fb5ec042..6f8ba7eb3 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionBuilder.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionBuilder.java @@ -28,6 +28,7 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; +import org.springframework.core.env.Environment; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.classreading.CachingMetadataReaderFactory; import org.springframework.core.type.classreading.MetadataReaderFactory; @@ -48,6 +49,7 @@ public class RepositoryBeanDefinitionBuilder { private final BeanDefinitionRegistry registry; private final RepositoryConfigurationExtension extension; private final ResourceLoader resourceLoader; + private final Environment environment; private final MetadataReaderFactory metadataReaderFactory; @@ -58,16 +60,20 @@ public class RepositoryBeanDefinitionBuilder { * @param registry must not be {@literal null}. * @param extension must not be {@literal null}. * @param resourceLoader must not be {@literal null}. + * @param environment must not be {@literal null}. */ public RepositoryBeanDefinitionBuilder(BeanDefinitionRegistry registry, RepositoryConfigurationExtension extension, - ResourceLoader resourceLoader) { + ResourceLoader resourceLoader, Environment environment) { - Assert.notNull(extension); + Assert.notNull(extension, "RepositoryConfigurationExtension must not be null!"); + Assert.notNull(resourceLoader, "ResourceLoader must not be null!"); + Assert.notNull(environment, "Environement must not be null!"); this.registry = registry; this.extension = extension; this.resourceLoader = resourceLoader; this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader); + this.environment = environment; } /** @@ -154,6 +160,7 @@ public class RepositoryBeanDefinitionBuilder { // Build classpath scanner and lookup bean definition ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false); + provider.setEnvironment(environment); provider.setResourceLoader(resourceLoader); provider.setResourcePattern(String.format(CUSTOM_IMPLEMENTATION_RESOURCE_PATTERN, className)); provider.setMetadataReaderFactory(metadataReaderFactory); diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionParser.java b/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionParser.java index acda849ba..c2fa165a1 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionParser.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionParser.java @@ -62,7 +62,8 @@ public class RepositoryBeanDefinitionParser implements BeanDefinitionParser { ResourceLoader resourceLoader = parser.getReaderContext().getResourceLoader(); XmlRepositoryConfigurationSource configSource = new XmlRepositoryConfigurationSource(element, parser, environment); - RepositoryConfigurationDelegate delegate = new RepositoryConfigurationDelegate(configSource, resourceLoader); + RepositoryConfigurationDelegate delegate = new RepositoryConfigurationDelegate(configSource, resourceLoader, + environment); for (BeanComponentDefinition definition : delegate.registerRepositoriesIn(parser.getRegistry(), extension)) { parser.registerBeanComponent(definition); diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java b/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java index 74a869664..c1f333f81 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java @@ -23,6 +23,8 @@ import org.springframework.context.EnvironmentAware; import org.springframework.context.ResourceLoaderAware; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.env.Environment; +import org.springframework.core.env.EnvironmentCapable; +import org.springframework.core.env.StandardEnvironment; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.AnnotationMetadata; import org.springframework.util.Assert; @@ -71,13 +73,34 @@ public abstract class RepositoryBeanDefinitionRegistrarSupport implements Import return; } + // TODO: remove once SPR-11744 gets fixed + Environment environment = defaultEnvironment(this.environment, resourceLoader); + AnnotationRepositoryConfigurationSource configurationSource = new AnnotationRepositoryConfigurationSource( annotationMetadata, getAnnotation(), resourceLoader, environment); - RepositoryConfigurationDelegate delegate = new RepositoryConfigurationDelegate(configurationSource, resourceLoader); + RepositoryConfigurationDelegate delegate = new RepositoryConfigurationDelegate(configurationSource, resourceLoader, + environment); delegate.registerRepositoriesIn(registry, getExtension()); } + /** + * Defaults the environment in case the given one is null. TODO: remove, once SPR-11744 gets fixed. + * + * @param environment + * @param resourceLoader + * @return + */ + private static Environment defaultEnvironment(Environment environment, ResourceLoader resourceLoader) { + + if (environment != null) { + return environment; + } + + return resourceLoader instanceof EnvironmentCapable ? ((EnvironmentCapable) resourceLoader).getEnvironment() + : new StandardEnvironment(); + } + /** * Return the annotation to obtain configuration information from. Will be wrappen into an * {@link AnnotationRepositoryConfigurationSource} so have a look at the constants in there for what annotation diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationDelegate.java b/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationDelegate.java index 6097a91da..4e6d20adc 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationDelegate.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationDelegate.java @@ -25,6 +25,9 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanNameGenerator; +import org.springframework.core.env.Environment; +import org.springframework.core.env.EnvironmentCapable; +import org.springframework.core.env.StandardEnvironment; import org.springframework.core.io.ResourceLoader; import org.springframework.util.Assert; @@ -42,6 +45,7 @@ public class RepositoryConfigurationDelegate { private final RepositoryConfigurationSource configurationSource; private final ResourceLoader resourceLoader; + private final Environment environment; private final BeanNameGenerator generator; private final boolean isXml; @@ -51,9 +55,24 @@ public class RepositoryConfigurationDelegate { * * @param configurationSource must not be {@literal null}. * @param resourceLoader must not be {@literal null}. + * @deprecated use constructor taking an {@link Environment}. */ + @Deprecated public RepositoryConfigurationDelegate(RepositoryConfigurationSource configurationSource, ResourceLoader resourceLoader) { + this(configurationSource, resourceLoader, null); + } + + /** + * Creates a new {@link RepositoryConfigurationDelegate} for the given {@link RepositoryConfigurationSource} and + * {@link ResourceLoader} and {@link Environment}. + * + * @param configurationSource must not be {@literal null}. + * @param resourceLoader must not be {@literal null}. + * @param environment must not be {@literal null}. + */ + public RepositoryConfigurationDelegate(RepositoryConfigurationSource configurationSource, + ResourceLoader resourceLoader, Environment environment) { this.isXml = configurationSource instanceof XmlRepositoryConfigurationSource; boolean isAnnotation = configurationSource instanceof AnnotationRepositoryConfigurationSource; @@ -68,6 +87,25 @@ public class RepositoryConfigurationDelegate { this.generator = generator; this.configurationSource = configurationSource; this.resourceLoader = resourceLoader; + this.environment = defaultEnvironment(environment, resourceLoader); + } + + /** + * Defaults the environment in case the given one is null. Used as fallback, in case the legacy constructor was + * invoked. + * + * @param environment can be {@literal null}. + * @param resourceLoader can be {@literal null}. + * @return + */ + private static Environment defaultEnvironment(Environment environment, ResourceLoader resourceLoader) { + + if (environment != null) { + return environment; + } + + return resourceLoader instanceof EnvironmentCapable ? ((EnvironmentCapable) resourceLoader).getEnvironment() + : new StandardEnvironment(); } /** @@ -82,7 +120,8 @@ public class RepositoryConfigurationDelegate { extension.registerBeansForRoot(registry, configurationSource); - RepositoryBeanDefinitionBuilder builder = new RepositoryBeanDefinitionBuilder(registry, extension, resourceLoader); + RepositoryBeanDefinitionBuilder builder = new RepositoryBeanDefinitionBuilder(registry, extension, resourceLoader, + environment); List definitions = new ArrayList(); for (RepositoryConfiguration configuration : extension diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java b/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java index 73d92e225..f8e890837 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java @@ -25,6 +25,7 @@ import org.springframework.core.env.Environment; import org.springframework.core.env.StandardEnvironment; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.filter.TypeFilter; +import org.springframework.util.Assert; /** * Base class to implement {@link RepositoryConfigurationSource}s. @@ -42,10 +43,12 @@ public abstract class RepositoryConfigurationSourceSupport implements Repository * Creates a new {@link RepositoryConfigurationSourceSupport} with the given environment. Defaults to a plain * {@link StandardEnvironment} in case the given argument is {@literal null}. * - * @param environment nullable, defaults to a {@link StandardEnvironment}. + * @param environment must not be {@literal null}. */ public RepositoryConfigurationSourceSupport(Environment environment) { - this.environment = environment == null ? new StandardEnvironment() : environment; + + Assert.notNull(environment, "Environment must not be null!"); + this.environment = environment; } /* diff --git a/src/test/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupportIntegrationTests.java b/src/test/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupportIntegrationTests.java index 342c7a0b3..c8fed7c8e 100644 --- a/src/test/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupportIntegrationTests.java +++ b/src/test/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupportIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * Copyright 2012-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,12 +18,16 @@ package org.springframework.data.repository.config; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Configuration; /** + * Integration tests for {@link RepositoryBeanDefinitionRegistrarSupport}. + * * @author Oliver Gierke */ public class RepositoryBeanDefinitionRegistrarSupportIntegrationTests { @@ -39,20 +43,37 @@ public class RepositoryBeanDefinitionRegistrarSupportIntegrationTests { } + AnnotationConfigApplicationContext context; + + @Before + public void setUp() { + this.context = new AnnotationConfigApplicationContext(TestConfig.class); + } + + @After + public void tearDown() { + + if (context != null) { + this.context.close(); + } + } + + /** + * @see DATACMNS-47 + */ @Test public void testBootstrappingWithInheritedConfigClasses() { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestConfig.class); - assertThat(context.getBean(MyRepository.class), is(notNullValue())); assertThat(context.getBean(MyOtherRepository.class), is(notNullValue())); } + /** + * @see DATACMNS-47 + */ @Test public void beanDefinitionSourceIsSetForJavaConfigScannedBeans() { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestConfig.class); - BeanDefinition definition = context.getBeanDefinition("myRepository"); assertThat(definition.getSource(), is(notNullValue())); }