Skip to content

Commit 259a1e0

Browse files
committed
DATACMNS-891 - Moved to constructor injection for RepositoryFactoryBeanSupport.
RepositoryFactoryBeanSupport now takes the repository interface as a constructor argument instead of as a setter. This makes sure that the container induced type prediction for factory beans actually wires the interface *before* it calls getObjectType() on the instance. This allows us to remove the extra infrastructure we had in place to predict the bean types and autowiring will just work out of the box. Adapted infrastructure code accordingly, removed obsolete infrastructure code and adapted test cases accordingly.
1 parent 3a24bee commit 259a1e0

17 files changed

+42
-476
lines changed

src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionBuilder.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,13 @@ public BeanDefinitionBuilder build(RepositoryConfiguration<?> configuration) {
8282
Assert.notNull(resourceLoader, "ResourceLoader must not be null!");
8383

8484
String factoryBeanName = configuration.getRepositoryFactoryBeanName();
85-
factoryBeanName = StringUtils.hasText(factoryBeanName) ? factoryBeanName : extension
86-
.getRepositoryFactoryClassName();
85+
factoryBeanName = StringUtils.hasText(factoryBeanName) ? factoryBeanName
86+
: extension.getRepositoryFactoryClassName();
8787

8888
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(factoryBeanName);
8989

9090
builder.getRawBeanDefinition().setSource(configuration.getSource());
91-
builder.addPropertyValue("repositoryInterface", configuration.getRepositoryInterface());
91+
builder.addConstructorArgValue(configuration.getRepositoryInterface());
9292
builder.addPropertyValue("queryLookupStrategyKey", configuration.getQueryLookupStrategyKey());
9393
builder.addPropertyValue("lazyInit", configuration.isLazyInit());
9494
builder.addPropertyValue("repositoryBaseClass", configuration.getRepositoryBaseClassName());
@@ -127,8 +127,8 @@ private String registerCustomImplementation(RepositoryConfiguration<?> configura
127127
return beanName;
128128
}
129129

130-
AbstractBeanDefinition beanDefinition = implementationDetector.detectCustomImplementation(
131-
configuration.getImplementationClassName(), configuration.getBasePackages());
130+
AbstractBeanDefinition beanDefinition = implementationDetector
131+
.detectCustomImplementation(configuration.getImplementationClassName(), configuration.getBasePackages());
132132

133133
if (null == beanDefinition) {
134134
return null;

src/main/java/org/springframework/data/repository/config/RepositoryBeanNameGenerator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry
6565
*/
6666
private Class<?> getRepositoryInterfaceFrom(BeanDefinition beanDefinition) {
6767

68-
Object value = beanDefinition.getPropertyValues().getPropertyValue("repositoryInterface").getValue();
68+
Object value = beanDefinition.getConstructorArgumentValues().getArgumentValue(0, Class.class).getValue();
6969

7070
if (value instanceof Class<?>) {
7171
return (Class<?>) value;

src/main/java/org/springframework/data/repository/config/RepositoryConfigurationExtensionSupport.java

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
import org.springframework.core.io.ResourceLoader;
3434
import org.springframework.data.repository.core.RepositoryMetadata;
3535
import org.springframework.data.repository.core.support.AbstractRepositoryMetadata;
36-
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport;
3736
import org.springframework.util.Assert;
3837
import org.springframework.util.StringUtils;
3938

@@ -50,8 +49,6 @@ public abstract class RepositoryConfigurationExtensionSupport implements Reposit
5049
private static final String CLASS_LOADING_ERROR = "%s - Could not load type %s using class loader %s.";
5150
private static final String MULTI_STORE_DROPPED = "Spring Data {} - Could not safely identify store assignment for repository candidate {}.";
5251

53-
private static final String FACTORY_BEAN_TYPE_PREDICTING_POST_PROCESSOR = "org.springframework.data.repository.core.support.FactoryBeanTypePredictingBeanPostProcessor";
54-
5552
/*
5653
* (non-Javadoc)
5754
* @see org.springframework.data.repository.config.RepositoryConfigurationExtension#getModuleName()
@@ -114,18 +111,8 @@ public String getDefaultNamedQueryLocation() {
114111
* (non-Javadoc)
115112
* @see org.springframework.data.repository.config.RepositoryConfigurationExtension#registerBeansForRoot(org.springframework.beans.factory.support.BeanDefinitionRegistry, org.springframework.data.repository.config.RepositoryConfigurationSource)
116113
*/
117-
public void registerBeansForRoot(BeanDefinitionRegistry registry, RepositoryConfigurationSource configurationSource) {
118-
119-
String typeName = RepositoryFactoryBeanSupport.class.getName();
120-
121-
BeanDefinitionBuilder builder = BeanDefinitionBuilder
122-
.rootBeanDefinition(FACTORY_BEAN_TYPE_PREDICTING_POST_PROCESSOR);
123-
builder.addConstructorArgValue(typeName);
124-
builder.addConstructorArgValue("repositoryInterface");
125-
126-
registerIfNotAlreadyRegistered(builder.getBeanDefinition(), registry, typeName.concat("_Predictor"),
127-
configurationSource.getSource());
128-
}
114+
public void registerBeansForRoot(BeanDefinitionRegistry registry,
115+
RepositoryConfigurationSource configurationSource) {}
129116

130117
/**
131118
* Returns the prefix of the module to be used to create the default location for Spring Data named queries.

src/main/java/org/springframework/data/repository/core/support/FactoryBeanTypePredictingBeanPostProcessor.java

Lines changed: 0 additions & 182 deletions
This file was deleted.

src/main/java/org/springframework/data/repository/core/support/RepositoryFactoryBeanSupport.java

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import org.springframework.beans.factory.BeanFactoryAware;
2525
import org.springframework.beans.factory.FactoryBean;
2626
import org.springframework.beans.factory.InitializingBean;
27-
import org.springframework.beans.factory.annotation.Required;
2827
import org.springframework.context.ApplicationEventPublisher;
2928
import org.springframework.context.ApplicationEventPublisherAware;
3029
import org.springframework.data.mapping.PersistentEntity;
@@ -53,10 +52,10 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>,
5352
implements InitializingBean, RepositoryFactoryInformation<S, ID>, FactoryBean<T>, BeanClassLoaderAware,
5453
BeanFactoryAware, ApplicationEventPublisherAware {
5554

56-
private RepositoryFactorySupport factory;
55+
private final Class<? extends T> repositoryInterface;
5756

57+
private RepositoryFactorySupport factory;
5858
private Key queryLookupStrategyKey;
59-
private Class<? extends T> repositoryInterface;
6059
private Class<?> repositoryBaseClass;
6160
private Object customImplementation;
6261
private NamedQueries namedQueries;
@@ -72,14 +71,13 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>,
7271
private RepositoryMetadata repositoryMetadata;
7372

7473
/**
75-
* Setter to inject the repository interface to implement.
74+
* Creates a new {@link RepositoryFactoryBeanSupport} for the given repository interface.
7675
*
77-
* @param repositoryInterface the repository interface to set
76+
* @param repositoryInterface must not be {@literal null}.
7877
*/
79-
@Required
80-
public void setRepositoryInterface(Class<? extends T> repositoryInterface) {
78+
protected RepositoryFactoryBeanSupport(Class<? extends T> repositoryInterface) {
8179

82-
Assert.notNull(repositoryInterface);
80+
Assert.notNull(repositoryInterface, "Repository interface must not be null!");
8381
this.repositoryInterface = repositoryInterface;
8482
}
8583

@@ -229,9 +227,8 @@ public T getObject() {
229227
* (non-Javadoc)
230228
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
231229
*/
232-
@SuppressWarnings("unchecked")
233230
public Class<? extends T> getObjectType() {
234-
return (Class<? extends T>) (null == repositoryInterface ? Repository.class : repositoryInterface);
231+
return repositoryInterface;
235232
}
236233

237234
/*
@@ -248,8 +245,6 @@ public boolean isSingleton() {
248245
*/
249246
public void afterPropertiesSet() {
250247

251-
Assert.notNull(repositoryInterface, "Repository interface must not be null on initialization!");
252-
253248
this.factory = createRepositoryFactory();
254249
this.factory.setQueryLookupStrategyKey(queryLookupStrategyKey);
255250
this.factory.setNamedQueries(namedQueries);

src/main/java/org/springframework/data/repository/core/support/TransactionalRepositoryFactoryBeanSupport.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@ public abstract class TransactionalRepositoryFactoryBeanSupport<T extends Reposi
4040
private RepositoryProxyPostProcessor exceptionPostProcessor;
4141
private boolean enableDefaultTransactions = true;
4242

43+
/**
44+
* Creates a new {@link TransactionalRepositoryFactoryBeanSupport} for the given repository interface.
45+
*
46+
* @param repositoryInterface must not be {@literal null}.
47+
*/
48+
protected TransactionalRepositoryFactoryBeanSupport(Class<? extends T> repositoryInterface) {
49+
super(repositoryInterface);
50+
}
51+
4352
/**
4453
* Setter to configure which transaction manager to be used. We have to use the bean name explicitly as otherwise the
4554
* qualifier of the {@link org.springframework.transaction.annotation.Transactional} annotation is used. By explicitly

src/test/java/org/springframework/data/repository/config/RepositoryBeanNameGeneratorUnitTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public void usesAnnotationValueIfAnnotationPresent() {
6262
private BeanDefinition getBeanDefinitionFor(Class<?> repositoryInterface) {
6363

6464
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(RepositoryFactoryBeanSupport.class);
65-
builder.addPropertyValue("repositoryInterface", repositoryInterface.getName());
65+
builder.addConstructorArgValue(repositoryInterface.getName());
6666
return builder.getBeanDefinition();
6767
}
6868

src/test/java/org/springframework/data/repository/config/RepositoryConfigurationExtensionSupportUnitTests.java

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,7 @@
2323
import java.util.Collections;
2424

2525
import org.junit.Test;
26-
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
2726
import org.springframework.context.annotation.Primary;
28-
import org.springframework.core.env.StandardEnvironment;
29-
import org.springframework.core.io.DefaultResourceLoader;
30-
import org.springframework.core.type.AnnotationMetadata;
31-
import org.springframework.core.type.StandardAnnotationMetadata;
3227
import org.springframework.data.repository.Repository;
3328
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
3429

@@ -65,26 +60,6 @@ public void considersRepositoryInterfaceExtendingStoreInterfaceStrictMatch() {
6560
assertThat(extension.isStrictRepositoryCandidate(ExtendingInterface.class), is(true));
6661
}
6762

68-
/**
69-
* @see DATACMNS-609
70-
*/
71-
@Test
72-
public void registersRepositoryInterfaceAwareBeanPostProcessorOnlyOnceForMultipleConfigurations() {
73-
74-
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
75-
AnnotationMetadata annotationMetadata = new StandardAnnotationMetadata(SampleConfiguration.class, true);
76-
77-
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
78-
StandardEnvironment environment = new StandardEnvironment();
79-
AnnotationRepositoryConfigurationSource configurationSource = new AnnotationRepositoryConfigurationSource(
80-
annotationMetadata, EnableRepositories.class, resourceLoader, environment);
81-
82-
extension.registerBeansForRoot(beanFactory, configurationSource);
83-
extension.registerBeansForRoot(beanFactory, configurationSource);
84-
85-
assertThat(beanFactory.getBeanDefinitionCount(), is(1));
86-
}
87-
8863
static class SampleRepositoryConfigurationExtension extends RepositoryConfigurationExtensionSupport {
8964

9065
@Override

0 commit comments

Comments
 (0)