Skip to content

Commit 3708b85

Browse files
xeounxzxump911de
authored andcommitted
Avoid multiple DeferredRepositoryInitializationListener registrations in RepositoryConfigurationDelegate.
Closes #3287 Original pull request: #3219
1 parent fcc3cd9 commit 3708b85

File tree

2 files changed

+39
-31
lines changed

2 files changed

+39
-31
lines changed

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

+14-22
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,6 @@
1515
*/
1616
package org.springframework.data.repository.config;
1717

18-
import java.lang.reflect.TypeVariable;
19-
import java.util.ArrayList;
20-
import java.util.Arrays;
21-
import java.util.Collection;
22-
import java.util.HashMap;
23-
import java.util.List;
24-
import java.util.Map;
25-
import java.util.stream.Collectors;
26-
2718
import org.apache.commons.logging.Log;
2819
import org.apache.commons.logging.LogFactory;
2920
import org.jspecify.annotations.Nullable;
@@ -32,12 +23,7 @@
3223
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
3324
import org.springframework.beans.factory.config.DependencyDescriptor;
3425
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
35-
import org.springframework.beans.factory.support.AutowireCandidateResolver;
36-
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
37-
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
38-
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
39-
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
40-
import org.springframework.beans.factory.support.RootBeanDefinition;
26+
import org.springframework.beans.factory.support.*;
4127
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
4228
import org.springframework.context.support.GenericApplicationContext;
4329
import org.springframework.core.ResolvableType;
@@ -57,6 +43,10 @@
5743
import org.springframework.util.Assert;
5844
import org.springframework.util.StopWatch;
5945

46+
import java.lang.reflect.TypeVariable;
47+
import java.util.*;
48+
import java.util.stream.Collectors;
49+
6050
/**
6151
* Delegate for configuration integration to reuse the general way of detecting repositories. Customization is done by
6252
* providing a configuration format specific {@link RepositoryConfigurationSource} (currently either XML or annotations
@@ -92,7 +82,7 @@ public class RepositoryConfigurationDelegate {
9282
* @param environment must not be {@literal null}.
9383
*/
9484
public RepositoryConfigurationDelegate(RepositoryConfigurationSource configurationSource,
95-
ResourceLoader resourceLoader, Environment environment) {
85+
ResourceLoader resourceLoader, Environment environment) {
9686

9787
this.isXml = configurationSource instanceof XmlRepositoryConfigurationSource;
9888
boolean isAnnotation = configurationSource instanceof AnnotationRepositoryConfigurationSource;
@@ -117,7 +107,7 @@ public RepositoryConfigurationDelegate(RepositoryConfigurationSource configurati
117107
* {@link Environment}.
118108
*/
119109
private static Environment defaultEnvironment(@Nullable Environment environment,
120-
@Nullable ResourceLoader resourceLoader) {
110+
@Nullable ResourceLoader resourceLoader) {
121111

122112
if (environment != null) {
123113
return environment;
@@ -136,7 +126,7 @@ private static Environment defaultEnvironment(@Nullable Environment environment,
136126
* @see org.springframework.beans.factory.support.BeanDefinitionRegistry
137127
*/
138128
public List<BeanComponentDefinition> registerRepositoriesIn(BeanDefinitionRegistry registry,
139-
RepositoryConfigurationExtension extension) {
129+
RepositoryConfigurationExtension extension) {
140130

141131
if (logger.isInfoEnabled()) {
142132
logger.info(LogMessage.format("Bootstrapping Spring Data %s repositories in %s mode.", //
@@ -222,7 +212,7 @@ public List<BeanComponentDefinition> registerRepositoriesIn(BeanDefinitionRegist
222212
}
223213

224214
private void registerAotComponents(BeanDefinitionRegistry registry, RepositoryConfigurationExtension extension,
225-
Map<String, RepositoryConfigurationAdapter<?>> metadataByRepositoryBeanName) {
215+
Map<String, RepositoryConfigurationAdapter<?>> metadataByRepositoryBeanName) {
226216

227217
BeanDefinitionBuilder repositoryAotProcessor = BeanDefinitionBuilder
228218
.rootBeanDefinition(extension.getRepositoryAotProcessor()).setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
@@ -245,7 +235,7 @@ private void registerAotComponents(BeanDefinitionRegistry registry, RepositoryCo
245235
* @param registry must not be {@literal null}.
246236
*/
247237
private static void potentiallyLazifyRepositories(Map<String, RepositoryConfiguration<?>> configurations,
248-
BeanDefinitionRegistry registry, BootstrapMode mode) {
238+
BeanDefinitionRegistry registry, BootstrapMode mode) {
249239

250240
if (!DefaultListableBeanFactory.class.isInstance(registry) || BootstrapMode.DEFAULT.equals(mode)) {
251241
return;
@@ -272,8 +262,10 @@ private static void potentiallyLazifyRepositories(Map<String, RepositoryConfigur
272262

273263
logger.debug("Registering deferred repository initialization listener.");
274264

275-
beanFactory.registerSingleton(DeferredRepositoryInitializationListener.class.getName(),
276-
new DeferredRepositoryInitializationListener(beanFactory));
265+
if (!beanFactory.containsBean(DeferredRepositoryInitializationListener.class.getName())) {
266+
beanFactory.registerSingleton(DeferredRepositoryInitializationListener.class.getName(),
267+
new DeferredRepositoryInitializationListener(beanFactory));
268+
}
277269
}
278270
}
279271

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

+25-9
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,6 @@
1515
*/
1616
package org.springframework.data.repository.config;
1717

18-
import static org.assertj.core.api.Assertions.*;
19-
20-
import java.lang.reflect.TypeVariable;
21-
import java.util.List;
22-
import java.util.Optional;
23-
import java.util.UUID;
24-
2518
import org.junit.jupiter.api.Test;
2619
import org.junit.jupiter.api.extension.ExtendWith;
2720
import org.mockito.Mockito;
@@ -59,11 +52,19 @@
5952
import org.springframework.data.repository.sample.AddressRepositoryClient;
6053
import org.springframework.data.repository.sample.ProductRepository;
6154

55+
import java.lang.reflect.TypeVariable;
56+
import java.util.List;
57+
import java.util.Optional;
58+
import java.util.UUID;
59+
60+
import static org.assertj.core.api.Assertions.assertThat;
61+
6262
/**
6363
* Unit tests for {@link RepositoryConfigurationDelegate}.
6464
*
6565
* @author Oliver Gierke
6666
* @author Mark Paluch
67+
* @author xeounxzxu
6768
* @soundtrack Richard Spaven - Tribute (Whole Other*)
6869
*/
6970
@ExtendWith(MockitoExtension.class)
@@ -109,7 +110,16 @@ void registersDeferredRepositoryInitializationListener() {
109110
var beanFactory = assertLazyRepositoryBeanSetup(DeferredConfig.class);
110111

111112
assertThat(beanFactory.getBeanNamesForType(DeferredRepositoryInitializationListener.class)).isNotEmpty();
113+
}
114+
115+
@Test
116+
void registersMultiDeferredRepositoryInitializationListener() {
117+
118+
var beanFactory = assertLazyRepositoryBeanSetup(DeferredConfig.class, OtherDeferredConfig.class);
112119

120+
assertThat(beanFactory.getBeanNamesForType(DeferredRepositoryInitializationListener.class)).isNotEmpty();
121+
assertThat(beanFactory.getBeanNamesForType(AddressRepository.class)).isNotEmpty();
122+
assertThat(beanFactory.getBeanNamesForType(ProductRepository.class)).isNotEmpty();
113123
}
114124

115125
@Test // DATACMNS-1832
@@ -276,9 +286,9 @@ void considersGenericLength() {
276286
assertThat(it.getGeneric(1).resolve()).isEqualTo(Person.class);
277287
}
278288

279-
private static ListableBeanFactory assertLazyRepositoryBeanSetup(Class<?> configClass) {
289+
private static ListableBeanFactory assertLazyRepositoryBeanSetup(Class<?>... componentClasses) {
280290

281-
var context = new AnnotationConfigApplicationContext(configClass);
291+
var context = new AnnotationConfigApplicationContext(componentClasses);
282292

283293
assertThat(context.getDefaultListableBeanFactory().getAutowireCandidateResolver())
284294
.isInstanceOf(LazyRepositoryInjectionPointResolver.class);
@@ -309,6 +319,12 @@ static class LazyConfig {}
309319
bootstrapMode = BootstrapMode.DEFERRED)
310320
static class DeferredConfig {}
311321

322+
@ComponentScan(basePackageClasses = ProductRepository.class)
323+
@EnableRepositories(basePackageClasses = ProductRepository.class,
324+
includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = AddressRepository.class),
325+
bootstrapMode = BootstrapMode.DEFERRED)
326+
static class OtherDeferredConfig {}
327+
312328
@EnableRepositories(basePackageClasses = MyOtherRepository.class,
313329
includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = MyOtherRepository.class),
314330
excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = MyOtherRepositoryImpl.class))

0 commit comments

Comments
 (0)