|
17 | 17 |
|
18 | 18 | import static org.assertj.core.api.Assertions.*;
|
19 | 19 |
|
| 20 | +import java.lang.reflect.TypeVariable; |
| 21 | +import java.util.List; |
| 22 | +import java.util.Optional; |
| 23 | +import java.util.UUID; |
| 24 | + |
20 | 25 | import org.junit.jupiter.api.Test;
|
21 | 26 | import org.junit.jupiter.api.extension.ExtendWith;
|
22 | 27 | import org.mockito.Mockito;
|
|
26 | 31 | import org.springframework.aop.framework.Advised;
|
27 | 32 | import org.springframework.aot.hint.RuntimeHints;
|
28 | 33 | import org.springframework.beans.factory.ListableBeanFactory;
|
| 34 | +import org.springframework.beans.factory.config.BeanDefinition; |
| 35 | +import org.springframework.beans.factory.parsing.BeanComponentDefinition; |
29 | 36 | import org.springframework.beans.factory.support.RootBeanDefinition;
|
30 | 37 | import org.springframework.context.annotation.AnnotationBeanNameGenerator;
|
31 | 38 | import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
32 | 39 | import org.springframework.context.annotation.ComponentScan;
|
33 | 40 | import org.springframework.context.annotation.ComponentScan.Filter;
|
34 | 41 | import org.springframework.context.annotation.FilterType;
|
35 | 42 | import org.springframework.context.support.GenericApplicationContext;
|
| 43 | +import org.springframework.core.ResolvableType; |
36 | 44 | import org.springframework.core.env.StandardEnvironment;
|
37 | 45 | import org.springframework.core.metrics.ApplicationStartup;
|
38 | 46 | import org.springframework.core.type.AnnotationMetadata;
|
39 | 47 | import org.springframework.core.type.StandardAnnotationMetadata;
|
| 48 | +import org.springframework.data.mapping.Person; |
| 49 | +import org.springframework.data.repository.Repository; |
40 | 50 | import org.springframework.data.repository.config.RepositoryConfigurationDelegate.LazyRepositoryInjectionPointResolver;
|
41 | 51 | import org.springframework.data.repository.config.annotated.MyAnnotatedRepository;
|
42 | 52 | import org.springframework.data.repository.config.annotated.MyAnnotatedRepositoryImpl;
|
43 | 53 | import org.springframework.data.repository.config.annotated.MyFragmentImpl;
|
44 | 54 | import org.springframework.data.repository.config.excluded.MyOtherRepositoryImpl;
|
45 | 55 | import org.springframework.data.repository.config.stereotype.MyStereotypeRepository;
|
46 | 56 | import org.springframework.data.repository.core.support.DummyRepositoryFactoryBean;
|
| 57 | +import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport; |
47 | 58 | import org.springframework.data.repository.sample.AddressRepository;
|
48 | 59 | import org.springframework.data.repository.sample.AddressRepositoryClient;
|
49 | 60 | import org.springframework.data.repository.sample.ProductRepository;
|
@@ -223,6 +234,38 @@ void registersAotPostProcessorForDifferentConfigurations() {
|
223 | 234 | assertThat(context.getBeanNamesForType(RepositoryRegistrationAotProcessor.class)).hasSize(2);
|
224 | 235 | }
|
225 | 236 |
|
| 237 | + @Test // GH-3074 |
| 238 | + void registersGenericsForIdConstrainingRepositoryFactoryBean() { |
| 239 | + |
| 240 | + ResolvableType it = registerBeanDefinition(IdConstrainingRepositoryFactoryBean.class); |
| 241 | + |
| 242 | + assertThat(it.getGenerics()).hasSize(2); |
| 243 | + assertThat(it.getGeneric(0).resolve()).isEqualTo(MyAnnotatedRepository.class); |
| 244 | + assertThat(it.getGeneric(1).resolve()).isEqualTo(Person.class); |
| 245 | + } |
| 246 | + |
| 247 | + @Test // GH-3074 |
| 248 | + void registersGenericsForDomainTypeConstrainingRepositoryFactoryBean() { |
| 249 | + |
| 250 | + ResolvableType it = registerBeanDefinition(DomainTypeConstrainingRepositoryFactoryBean.class); |
| 251 | + |
| 252 | + assertThat(it.getGenerics()).hasSize(2); |
| 253 | + assertThat(it.getGeneric(0).resolve()).isEqualTo(MyAnnotatedRepository.class); |
| 254 | + assertThat(it.getGeneric(1).resolve()).isEqualTo(String.class); |
| 255 | + } |
| 256 | + |
| 257 | + @Test // GH-3074 |
| 258 | + void registersGenericsForAdditionalGenericsRepositoryFactoryBean() { |
| 259 | + |
| 260 | + ResolvableType it = registerBeanDefinition(AdditionalGenericsRepositoryFactoryBean.class); |
| 261 | + |
| 262 | + assertThat(it.getGenerics()).hasSize(4); |
| 263 | + assertThat(it.getGeneric(0).resolve()).isEqualTo(MyAnnotatedRepository.class); |
| 264 | + assertThat(it.getGeneric(1).resolve()).isEqualTo(Person.class); |
| 265 | + assertThat(it.getGeneric(2).resolve()).isEqualTo(String.class); |
| 266 | + assertThat(it.getGeneric(3).getType()).isInstanceOf(TypeVariable.class); |
| 267 | + } |
| 268 | + |
226 | 269 | private static ListableBeanFactory assertLazyRepositoryBeanSetup(Class<?> configClass) {
|
227 | 270 |
|
228 | 271 | var context = new AnnotationConfigApplicationContext(configClass);
|
@@ -279,4 +322,56 @@ protected String getModulePrefix() {
|
279 | 322 | return "commons";
|
280 | 323 | }
|
281 | 324 | }
|
| 325 | + |
| 326 | + private ResolvableType registerBeanDefinition(Class<?> repositoryFactoryType) { |
| 327 | + |
| 328 | + AnnotationMetadata metadata = AnnotationMetadata.introspect(AnnotatedBeanNamesConfig.class); |
| 329 | + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); |
| 330 | + |
| 331 | + RepositoryConfigurationSource source = new AnnotationRepositoryConfigurationSource(metadata, |
| 332 | + EnableRepositories.class, context, context.getEnvironment(), |
| 333 | + context.getDefaultListableBeanFactory(), new AnnotationBeanNameGenerator()) { |
| 334 | + |
| 335 | + @Override |
| 336 | + public Optional<String> getRepositoryFactoryBeanClassName() { |
| 337 | + return Optional.of(repositoryFactoryType.getName()); |
| 338 | + } |
| 339 | + }; |
| 340 | + |
| 341 | + RepositoryConfigurationDelegate delegate = new RepositoryConfigurationDelegate(source, context, |
| 342 | + context.getEnvironment()); |
| 343 | + |
| 344 | + List<BeanComponentDefinition> repositories = delegate.registerRepositoriesIn(context, extension); |
| 345 | + |
| 346 | + assertThat(repositories).hasSize(1).element(0) |
| 347 | + .extracting(BeanComponentDefinition::getBeanDefinition) |
| 348 | + .extracting(BeanDefinition::getResolvableType) |
| 349 | + .isNotNull(); |
| 350 | + |
| 351 | + return repositories.get(0).getBeanDefinition().getResolvableType(); |
| 352 | + } |
| 353 | + |
| 354 | + static abstract class IdConstrainingRepositoryFactoryBean<T extends Repository<S, UUID>, S> |
| 355 | + extends RepositoryFactoryBeanSupport<T, S, UUID> { |
| 356 | + |
| 357 | + protected IdConstrainingRepositoryFactoryBean(Class<? extends T> repositoryInterface) { |
| 358 | + super(repositoryInterface); |
| 359 | + } |
| 360 | + } |
| 361 | + |
| 362 | + static abstract class DomainTypeConstrainingRepositoryFactoryBean<T extends Repository<Person, ID>, ID> |
| 363 | + extends RepositoryFactoryBeanSupport<T, Person, ID> { |
| 364 | + |
| 365 | + protected DomainTypeConstrainingRepositoryFactoryBean(Class<? extends T> repositoryInterface) { |
| 366 | + super(repositoryInterface); |
| 367 | + } |
| 368 | + } |
| 369 | + |
| 370 | + static abstract class AdditionalGenericsRepositoryFactoryBean<T extends Repository<S, ID>, S, ID, R> |
| 371 | + extends RepositoryFactoryBeanSupport<T, S, ID> { |
| 372 | + |
| 373 | + protected AdditionalGenericsRepositoryFactoryBean(Class<? extends T> repositoryInterface) { |
| 374 | + super(repositoryInterface); |
| 375 | + } |
| 376 | + } |
282 | 377 | }
|
0 commit comments