DATACMNS-1018 - Reinstantiated ability to customize repository factory bean through annotation and XML namespace.

The refactoring for DATACMNS-867 has dropped support to customize the repository factory bean class on both the @Enable-annotations and the XML namespace. Reintroduced this feature, added a test case and moved the fallback into the value that's defined by the configuration extension inside DefaultRepositoryConfiguration.
This commit is contained in:
Oliver Gierke
2017-03-24 14:12:25 +01:00
parent 6b5b65804e
commit 11dc67da2c
13 changed files with 93 additions and 39 deletions

View File

@@ -211,10 +211,11 @@ public class AnnotationRepositoryConfigurationSource extends RepositoryConfigura
/*
* (non-Javadoc)
* @see org.springframework.data.repository.config.RepositoryConfigurationSource#getRepositoryFactoryBeanName()
* @see org.springframework.data.repository.config.RepositoryConfigurationSource#getRepositoryFactoryBeanClassName()
*/
public String getRepositoryFactoryBeanName() {
return attributes.getClass(REPOSITORY_FACTORY_BEAN_CLASS).getName();
@Override
public Optional<String> getRepositoryFactoryBeanClassName() {
return Optional.of(attributes.getClass(REPOSITORY_FACTORY_BEAN_CLASS).getName());
}
/*

View File

@@ -40,6 +40,7 @@ public class DefaultRepositoryConfiguration<T extends RepositoryConfigurationSou
private final @NonNull T configurationSource;
private final @NonNull BeanDefinition definition;
private final @NonNull RepositoryConfigurationExtension extension;
/*
* (non-Javadoc)
@@ -133,7 +134,18 @@ public class DefaultRepositoryConfiguration<T extends RepositoryConfigurationSou
return configurationSource.getRepositoryBaseClassName();
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.repository.config.RepositoryConfiguration#getRepositoryFactoryBeanClassName()
*/
@Override
public String getRepositoryFactoryBeanClassName() {
return configurationSource.getRepositoryFactoryBeanClassName()
.orElseGet(() -> extension.getRepositoryFactoryBeanClassName());
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.config.RepositoryConfiguration#isLazyInit()
*/

View File

@@ -84,7 +84,8 @@ class RepositoryBeanDefinitionBuilder {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null!");
Assert.notNull(resourceLoader, "ResourceLoader must not be null!");
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(extension.getRepositoryFactoryClassName());
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.rootBeanDefinition(configuration.getRepositoryFactoryBeanClassName());
builder.getRawBeanDefinition().setSource(configuration.getSource());
builder.addConstructorArgValue(configuration.getRepositoryInterface());

View File

@@ -79,6 +79,13 @@ public interface RepositoryConfiguration<T extends RepositoryConfigurationSource
*/
Optional<String> getRepositoryBaseClassName();
/**
* Returns the name of the repository factory bean class to be used.
*
* @return
*/
String getRepositoryFactoryBeanClassName();
/**
* Returns the source of the {@link RepositoryConfiguration}.
*

View File

@@ -137,7 +137,7 @@ public class RepositoryConfigurationDelegate {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(REPOSITORY_REGISTRATION, extension.getModuleName(), beanName,
configuration.getRepositoryInterface(), extension.getRepositoryFactoryClassName());
configuration.getRepositoryInterface(), configuration.getRepositoryFactoryBeanClassName());
}
beanDefinition.setAttribute(FACTORY_BEAN_OBJECT_TYPE, configuration.getRepositoryInterface());

View File

@@ -76,7 +76,7 @@ public interface RepositoryConfigurationExtension {
*
* @return
*/
String getRepositoryFactoryClassName();
String getRepositoryFactoryBeanClassName();
/**
* Callback to register additional bean definitions for a {@literal repositories} root node. This usually includes

View File

@@ -232,7 +232,7 @@ public abstract class RepositoryConfigurationExtensionSupport implements Reposit
/**
* Creates a actual {@link RepositoryConfiguration} instance for the given {@link RepositoryConfigurationSource} and
* interface name. Defaults to the {@link DefaultRepositoryConfiguration} but allows sub-classes to override this to
* customize the behaviour.
* customize the behavior.
*
* @param definition will never be {@literal null} or empty.
* @param configSource will never be {@literal null}.
@@ -240,7 +240,7 @@ public abstract class RepositoryConfigurationExtensionSupport implements Reposit
*/
protected <T extends RepositoryConfigurationSource> RepositoryConfiguration<T> getRepositoryConfiguration(
BeanDefinition definition, T configSource) {
return new DefaultRepositoryConfiguration<>(configSource, definition);
return new DefaultRepositoryConfiguration<>(configSource, definition, this);
}
/**

View File

@@ -57,7 +57,7 @@ public interface RepositoryConfigurationSource {
/**
* Returns the configured postfix to be used for looking up custom implementation classes.
*
* @return the postfix to use or {@literal null} in case none is configured.
* @return the postfix to use or {@link Optional#empty()} in case none is configured.
*/
Optional<String> getRepositoryImplementationPostfix();
@@ -67,14 +67,21 @@ public interface RepositoryConfigurationSource {
Optional<String> getNamedQueryLocation();
/**
* Returns the name of the repository base class to be used or {@literal null} if the store specific defaults shall be
* applied.
* Returns the name of the repository base class to be used or {@link Optional#empty()} if the store specific defaults
* shall be applied.
*
* @return
* @since 1.11
*/
Optional<String> getRepositoryBaseClassName();
/**
* Returns the name of the repository factory bean class or {@link Optional#empty()} if not defined in the source.
*
* @return
*/
Optional<String> getRepositoryFactoryBeanClassName();
/**
* Returns the source {@link BeanDefinition}s of the repository interfaces to create repository instances for.
*
@@ -88,7 +95,7 @@ public interface RepositoryConfigurationSource {
* camel-case.
*
* @param name must not be {@literal null} or empty.
* @return the attribute with the given name or {@literal null} if not configured or empty.
* @return the attribute with the given name or {@link Optional#empty()} if not configured or empty.
* @since 1.8
*/
Optional<String> getAttribute(String name);

View File

@@ -24,7 +24,6 @@ import org.springframework.core.env.Environment;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.data.config.TypeFilterParser;
import org.springframework.data.config.TypeFilterParser.Type;
import org.springframework.data.repository.query.QueryLookupStrategy;
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
import org.springframework.data.util.ParsingUtils;
import org.springframework.util.Assert;
@@ -162,6 +161,15 @@ public class XmlRepositoryConfigurationSource extends RepositoryConfigurationSou
return getNullDefaultedAttribute(element, REPOSITORY_BASE_CLASS_NAME);
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.config.RepositoryConfigurationSource#getRepositoryFactoryBeanClassName()
*/
@Override
public Optional<String> getRepositoryFactoryBeanClassName() {
return getNullDefaultedAttribute(element, REPOSITORY_FACTORY_BEAN_CLASS_NAME);
}
private Optional<String> getNullDefaultedAttribute(Element element, String attributeName) {
String attribute = element.getAttribute(attributeName);
@@ -175,8 +183,7 @@ public class XmlRepositoryConfigurationSource extends RepositoryConfigurationSou
@Override
public boolean shouldConsiderNestedRepositories() {
return getNullDefaultedAttribute(element, CONSIDER_NESTED_REPOSITORIES).map(Boolean::parseBoolean)
.orElse(false);
return getNullDefaultedAttribute(element, CONSIDER_NESTED_REPOSITORIES).map(Boolean::parseBoolean).orElse(false);
}
/*

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.data.repository.core.support;
import lombok.Getter;
import java.io.Serializable;
import java.util.List;
@@ -31,6 +33,7 @@ import org.springframework.util.Assert;
* @author Oliver Gierke
* @author Thomas Darimont
*/
@Getter
public class DefaultRepositoryMetadata extends AbstractRepositoryMetadata {
private static final String MUST_BE_A_REPOSITORY = String.format("Given type must be assignable to %s!",
@@ -53,24 +56,6 @@ public class DefaultRepositoryMetadata extends AbstractRepositoryMetadata {
this.domainType = resolveDomainType(repositoryInterface);
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.core.RepositoryMetadata#getDomainType()
*/
@Override
public Class<?> getDomainType() {
return this.domainType;
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.core.RepositoryMetadata#getIdType()
*/
@Override
public Class<? extends Serializable> getIdType() {
return this.idType;
}
@SuppressWarnings("unchecked")
private Class<? extends Serializable> resolveIdType(Class<?> repositoryInterface) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2013 the original author or authors.
* Copyright 2012-2017 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.
@@ -16,11 +16,18 @@
package org.springframework.data.repository.config;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import lombok.EqualsAndHashCode;
import lombok.Value;
import java.util.Optional;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
@@ -34,11 +41,13 @@ public class DefaultRepositoryConfigurationUnitTests {
@Mock RepositoryConfigurationSource source;
BeanDefinition definition = new RootBeanDefinition("com.acme.MyRepository");
RepositoryConfigurationExtension extension = new SimplerRepositoryConfigurationExtension("factory", "module");
@Test
public void supportsBasicConfiguration() {
RepositoryConfiguration<RepositoryConfigurationSource> configuration = new DefaultRepositoryConfiguration<>(
source, new RootBeanDefinition("com.acme.MyRepository"));
RepositoryConfiguration<RepositoryConfigurationSource> configuration = getConfiguration(source);
assertThat(configuration.getConfigurationSource()).isEqualTo(source);
assertThat(configuration.getImplementationBeanName()).isEqualTo("myRepositoryImpl");
@@ -47,4 +56,28 @@ public class DefaultRepositoryConfigurationUnitTests {
assertThat(configuration.getQueryLookupStrategyKey()).isEqualTo(Key.CREATE_IF_NOT_FOUND);
assertThat(configuration.isLazyInit()).isFalse();
}
@Test // DATACMNS-1018
public void usesExtensionFactoryBeanClassNameIfNoneDefinedInSource() {
assertThat(getConfiguration(source).getRepositoryFactoryBeanClassName()).isEqualTo("factory");
}
@Test // DATACMNS-1018
public void prefersSourcesRepositoryFactoryBeanClass() {
when(source.getRepositoryFactoryBeanClassName()).thenReturn(Optional.of("custom"));
assertThat(getConfiguration(source).getRepositoryFactoryBeanClassName()).isEqualTo("custom");
}
private DefaultRepositoryConfiguration<RepositoryConfigurationSource> getConfiguration(
RepositoryConfigurationSource source) {
return new DefaultRepositoryConfiguration<>(source, definition, extension);
}
@Value
@EqualsAndHashCode(callSuper = true)
private static class SimplerRepositoryConfigurationExtension extends RepositoryConfigurationExtensionSupport {
String repositoryFactoryBeanClassName, modulePrefix;
}
}

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.data.repository.config;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import java.lang.annotation.Annotation;
@@ -120,7 +121,7 @@ public class RepositoryBeanDefinitionRegistrarSupportUnitTests {
static class DummyConfigurationExtension extends RepositoryConfigurationExtensionSupport {
public String getRepositoryFactoryClassName() {
public String getRepositoryFactoryBeanClassName() {
return DummyRepositoryFactoryBean.class.getName();
}

View File

@@ -66,7 +66,7 @@ public class RepositoryConfigurationExtensionSupportUnitTests {
}
@Override
public String getRepositoryFactoryClassName() {
public String getRepositoryFactoryBeanClassName() {
return RepositoryFactorySupport.class.getName();
}