Browse Source

DATACMNS-420 - Introduced RepositoryConfigurationDelegate.

RepositoryConfigurationDelegate allows to easily trigger repository BeanDefinitions to be registered independently of the client API (XML or annotation configuration support). Refactored the existing configuration base classes to use the newly introduced class. Removed defaulting of infrastructure components needed for Spring 3.1 compatibility.
pull/61/head
Oliver Gierke 12 years ago
parent
commit
a5eedad48f
  1. 57
      src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionParser.java
  2. 79
      src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java
  3. 113
      src/main/java/org/springframework/data/repository/config/RepositoryConfigurationDelegate.java
  4. 7
      src/test/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupportUnitTests.java

57
src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionParser.java

@ -17,13 +17,9 @@ package org.springframework.data.repository.config; @@ -17,13 +17,9 @@ package org.springframework.data.repository.config;
import static org.springframework.beans.factory.support.BeanDefinitionReaderUtils.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.parsing.ReaderContext;
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.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
@ -41,8 +37,6 @@ import org.w3c.dom.Element; @@ -41,8 +37,6 @@ import org.w3c.dom.Element;
*/
public class RepositoryBeanDefinitionParser implements BeanDefinitionParser {
private static final Logger LOGGER = LoggerFactory.getLogger(RepositoryBeanDefinitionParser.class);
private final RepositoryConfigurationExtension extension;
/**
@ -65,15 +59,15 @@ public class RepositoryBeanDefinitionParser implements BeanDefinitionParser { @@ -65,15 +59,15 @@ public class RepositoryBeanDefinitionParser implements BeanDefinitionParser {
try {
Environment environment = parser.getDelegate().getEnvironment();
ResourceLoader resourceLoader = parser.getReaderContext().getResourceLoader();
XmlRepositoryConfigurationSource configSource = new XmlRepositoryConfigurationSource(element, parser, environment);
RepositoryConfigurationDelegate delegate = new RepositoryConfigurationDelegate(configSource, resourceLoader);
for (RepositoryConfiguration<XmlRepositoryConfigurationSource> config : extension.getRepositoryConfigurations(
configSource, parser.getReaderContext().getResourceLoader())) {
registerGenericRepositoryFactoryBean(config, parser);
for (BeanComponentDefinition definition : delegate.registerRepositoriesIn(parser.getRegistry(), extension)) {
parser.registerBeanComponent(definition);
}
extension.registerBeansForRoot(parser.getRegistry(), configSource);
} catch (RuntimeException e) {
handleError(e, element, parser.getReaderContext());
}
@ -85,47 +79,6 @@ public class RepositoryBeanDefinitionParser implements BeanDefinitionParser { @@ -85,47 +79,6 @@ public class RepositoryBeanDefinitionParser implements BeanDefinitionParser {
reader.error(e.getMessage(), reader.extractSource(source), e);
}
/**
* Registers a generic repository factory bean for a bean with the given name and the provided configuration context.
*
* @param parser
* @param name
* @param context
*/
private void registerGenericRepositoryFactoryBean(
RepositoryConfiguration<XmlRepositoryConfigurationSource> configuration, ParserContext parser) {
ResourceLoader resourceLoader = parser.getReaderContext().getResourceLoader();
BeanDefinitionRegistry registry = parser.getRegistry();
RepositoryBeanDefinitionBuilder definitionBuilder = new RepositoryBeanDefinitionBuilder(registry, extension,
resourceLoader);
try {
BeanDefinitionBuilder builder = definitionBuilder.build(configuration);
extension.postProcess(builder, configuration.getConfigurationSource());
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
beanDefinition.setSource(configuration.getSource());
RepositoryBeanNameGenerator generator = new RepositoryBeanNameGenerator();
generator.setBeanClassLoader(parser.getReaderContext().getBeanClassLoader());
String beanName = generator.generateBeanName(beanDefinition, registry);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Registering repository: " + beanName + " - Interface: " + configuration.getRepositoryInterface()
+ " - Factory: " + extension.getRepositoryFactoryClassName());
}
BeanComponentDefinition definition = new BeanComponentDefinition(beanDefinition, beanName);
parser.registerBeanComponent(definition);
} catch (RuntimeException e) {
handleError(e, configuration.getConfigurationSource().getElement(), parser.getReaderContext());
}
}
/**
* Returns whether the given {@link BeanDefinitionRegistry} already contains a bean of the given type assuming the
* bean name has been autogenerated.

79
src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java

@ -17,20 +17,15 @@ package org.springframework.data.repository.config; @@ -17,20 +17,15 @@ package org.springframework.data.repository.config;
import java.lang.annotation.Annotation;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
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.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* Base class to implement {@link ImportBeanDefinitionRegistrar}s to enable repository
@ -38,21 +33,11 @@ import org.springframework.util.ClassUtils; @@ -38,21 +33,11 @@ import org.springframework.util.ClassUtils;
* @author Oliver Gierke
*/
public abstract class RepositoryBeanDefinitionRegistrarSupport implements ImportBeanDefinitionRegistrar,
BeanClassLoaderAware, ResourceLoaderAware, EnvironmentAware {
ResourceLoaderAware, EnvironmentAware {
private ResourceLoader resourceLoader;
private ClassLoader beanClassLoader;
private Environment environment;
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader(java.lang.ClassLoader)
*/
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
}
/*
* (non-Javadoc)
* @see org.springframework.context.ResourceLoaderAware#setResourceLoader(org.springframework.core.io.ResourceLoader)
@ -77,72 +62,20 @@ public abstract class RepositoryBeanDefinitionRegistrarSupport implements Import @@ -77,72 +62,20 @@ public abstract class RepositoryBeanDefinitionRegistrarSupport implements Import
*/
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {
Assert.notNull(annotationMetadata);
Assert.notNull(registry);
Assert.notNull(resourceLoader, "ResourceLoader must not be null!");
Assert.notNull(annotationMetadata, "AnnotationMetadata must not be null!");
Assert.notNull(registry, "BeanDefinitionRegistry must not be null!");
// Guard against calls for sub-classes
if (annotationMetadata.getAnnotationAttributes(getAnnotation().getName()) == null) {
return;
}
defaultExternalResources(registry);
AnnotationRepositoryConfigurationSource configurationSource = new AnnotationRepositoryConfigurationSource(
annotationMetadata, getAnnotation(), environment);
RepositoryConfigurationExtension extension = getExtension();
extension.registerBeansForRoot(registry, configurationSource);
RepositoryBeanNameGenerator generator = new RepositoryBeanNameGenerator();
generator.setBeanClassLoader(beanClassLoader);
RepositoryBeanDefinitionBuilder builder = new RepositoryBeanDefinitionBuilder(registry, extension, resourceLoader);
for (RepositoryConfiguration<AnnotationRepositoryConfigurationSource> configuration : extension
.getRepositoryConfigurations(configurationSource, resourceLoader)) {
BeanDefinitionBuilder definitionBuilder = builder.build(configuration);
extension.postProcess(definitionBuilder, configurationSource);
String beanName = generator.generateBeanName(definitionBuilder.getBeanDefinition(), registry);
registry.registerBeanDefinition(beanName, definitionBuilder.getBeanDefinition());
}
}
/**
* Workaround the lack of injectability of external resources into {@link ImportBeanDefinitionRegistrar}s in the
* Spring 3.1 timeline. We populate {@link #beanClassLoader} and default the {@link #resourceLoader} in case they
* haven't been set until a call to this method.
*
* @param registry must not be {@literal null}.
* @see SPR-9568
*/
private void defaultExternalResources(BeanDefinitionRegistry registry) {
if (beanClassLoader == null) {
this.beanClassLoader = getBeanClassLoader(registry);
}
if (resourceLoader == null) {
this.resourceLoader = new DefaultResourceLoader(this.beanClassLoader);
}
}
/**
* Returns the bean class loader contained in the given registry if it is a {@link ConfigurableBeanFactory}. Falls
* back to the {@link ResourceLoader}'s {@link ClassLoader} or the global default one if that one is {@literal null}
* in turn.
*
* @param registry must not be {@literal null}.
* @return
*/
private ClassLoader getBeanClassLoader(BeanDefinitionRegistry registry) {
if (registry instanceof ConfigurableBeanFactory) {
return ((ConfigurableBeanFactory) registry).getBeanClassLoader();
}
return resourceLoader == null ? ClassUtils.getDefaultClassLoader() : resourceLoader.getClassLoader();
RepositoryConfigurationDelegate delegate = new RepositoryConfigurationDelegate(configurationSource, resourceLoader);
delegate.registerRepositoriesIn(registry, getExtension());
}
/**

113
src/main/java/org/springframework/data/repository/config/RepositoryConfigurationDelegate.java

@ -0,0 +1,113 @@ @@ -0,0 +1,113 @@
/*
* Copyright 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.repository.config;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
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.io.ResourceLoader;
import org.springframework.util.Assert;
/**
* Delegate for configuration integration to reuse the general way of detecting repositories. Customization is done by
* providing a configuration format specific {@link RepositoryConfigurationSource} (currently either XML or annotations
* are supported). The actual registration can then be triggered for different {@link RepositoryConfigurationExtension}
* s.
*
* @author Oliver Gierke
*/
public class RepositoryConfigurationDelegate {
private static final Logger LOGGER = LoggerFactory.getLogger(RepositoryConfigurationDelegate.class);
private final RepositoryConfigurationSource configurationSource;
private final ResourceLoader resourceLoader;
private final BeanNameGenerator generator;
private final boolean isXml;
/**
* Creates a new {@link RepositoryConfigurationDelegate} for the given {@link RepositoryConfigurationSource} and
* {@link ResourceLoader}.
*
* @param configurationSource must not be {@literal null}.
* @param resourceLoader must not be {@literal null}.
*/
public RepositoryConfigurationDelegate(RepositoryConfigurationSource configurationSource,
ResourceLoader resourceLoader) {
this.isXml = configurationSource instanceof XmlRepositoryConfigurationSource;
boolean isAnnotation = configurationSource instanceof AnnotationRepositoryConfigurationSource;
Assert.isTrue(isXml || isAnnotation,
"Configuration source must either be an Xml- or an AnnotationBasedConfigurationSource!");
Assert.notNull(resourceLoader);
RepositoryBeanNameGenerator generator = new RepositoryBeanNameGenerator();
generator.setBeanClassLoader(resourceLoader.getClassLoader());
this.generator = generator;
this.configurationSource = configurationSource;
this.resourceLoader = resourceLoader;
}
/**
* Registers the found repositories in the given {@link BeanDefinitionRegistry}.
*
* @param registry
* @param extension
* @return {@link BeanComponentDefinition}s for all repository bean definitions found.
*/
public List<BeanComponentDefinition> registerRepositoriesIn(BeanDefinitionRegistry registry,
RepositoryConfigurationExtension extension) {
extension.registerBeansForRoot(registry, configurationSource);
RepositoryBeanDefinitionBuilder builder = new RepositoryBeanDefinitionBuilder(registry, extension, resourceLoader);
List<BeanComponentDefinition> definitions = new ArrayList<BeanComponentDefinition>();
for (RepositoryConfiguration<? extends RepositoryConfigurationSource> configuration : extension
.getRepositoryConfigurations(configurationSource, resourceLoader)) {
BeanDefinitionBuilder definitionBuilder = builder.build(configuration);
if (isXml) {
extension.postProcess(definitionBuilder, (XmlRepositoryConfigurationSource) configurationSource);
} else {
extension.postProcess(definitionBuilder, (AnnotationRepositoryConfigurationSource) configurationSource);
}
AbstractBeanDefinition beanDefinition = definitionBuilder.getBeanDefinition();
String beanName = generator.generateBeanName(beanDefinition, registry);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Registering repository: " + beanName + " - Interface: " + configuration.getRepositoryInterface()
+ " - Factory: " + extension.getRepositoryFactoryClassName());
}
registry.registerBeanDefinition(beanName, beanDefinition);
definitions.add(new BeanComponentDefinition(beanDefinition, beanName));
}
return definitions;
}
}

7
src/test/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupportUnitTests.java

@ -1,5 +1,5 @@ @@ -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.
@ -27,6 +27,7 @@ import org.mockito.runners.MockitoJUnitRunner; @@ -27,6 +27,7 @@ import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.StandardAnnotationMetadata;
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport;
@ -87,6 +88,10 @@ public class RepositoryBeanDefinitionRegistrarSupportUnitTests { @@ -87,6 +88,10 @@ public class RepositoryBeanDefinitionRegistrarSupportUnitTests {
static class DummyRegistrar extends RepositoryBeanDefinitionRegistrarSupport {
DummyRegistrar() {
setResourceLoader(new DefaultResourceLoader());
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport#getAnnotation()

Loading…
Cancel
Save