@@ -25,6 +25,8 @@ import org.assertj.core.api.AbstractAssert;
|
||||
import org.springframework.aot.generate.GenerationContext;
|
||||
import org.springframework.aot.hint.ClassProxyHint;
|
||||
import org.springframework.aot.hint.JdkProxyHint;
|
||||
import org.springframework.aot.hint.ProxyHintsPredicates;
|
||||
import org.springframework.aot.hint.RuntimeHintsPredicates;
|
||||
|
||||
/**
|
||||
* AssertJ {@link AbstractAssert Assertion} for code contributions originating from
|
||||
@@ -45,9 +47,9 @@ public class CodeContributionAssert extends AbstractAssert<CodeContributionAsser
|
||||
public CodeContributionAssert contributesReflectionFor(Class<?>... types) {
|
||||
|
||||
for (Class<?> type : types) {
|
||||
assertThat(this.actual.getRuntimeHints().reflection().getTypeHint(type))
|
||||
assertThat(this.actual.getRuntimeHints())
|
||||
.describedAs("No reflection entry found for [%s]", type)
|
||||
.isNotNull();
|
||||
.matches(RuntimeHintsPredicates.reflection().onType(type));
|
||||
}
|
||||
|
||||
return this;
|
||||
@@ -56,9 +58,9 @@ public class CodeContributionAssert extends AbstractAssert<CodeContributionAsser
|
||||
public CodeContributionAssert doesNotContributeReflectionFor(Class<?>... types) {
|
||||
|
||||
for (Class<?> type : types) {
|
||||
assertThat(this.actual.getRuntimeHints().reflection().getTypeHint(type))
|
||||
assertThat(this.actual.getRuntimeHints())
|
||||
.describedAs("Reflection entry found for [%s]", type)
|
||||
.isNull();
|
||||
.matches(RuntimeHintsPredicates.reflection().onType(type).negate());
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
@@ -20,37 +20,46 @@ import static org.assertj.core.api.Assertions.*;
|
||||
import java.util.Collections;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aot.generate.ClassNameGenerator;
|
||||
import org.springframework.aot.generate.DefaultGenerationContext;
|
||||
import org.springframework.aot.generate.InMemoryGeneratedFiles;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.aot.hint.RuntimeHintsPredicates;
|
||||
import org.springframework.beans.factory.aot.BeanRegistrationAotContribution;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RegisteredBean;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.data.ManagedTypes;
|
||||
import org.springframework.data.domain.ManagedTypes;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
class ManagedTypesRegistrationAotProcessorUnitTests {
|
||||
class ManagedTypesBeanRegistrationAotProcessorUnitTests {
|
||||
|
||||
final RootBeanDefinition managedTypesDefinition = (RootBeanDefinition) BeanDefinitionBuilder
|
||||
.rootBeanDefinition(ManagedTypes.class).setFactoryMethod("of")
|
||||
.rootBeanDefinition(ManagedTypes.class).setFactoryMethod("fromIterable")
|
||||
.addConstructorArgValue(Collections.singleton(A.class)).getBeanDefinition();
|
||||
|
||||
final RootBeanDefinition myManagedTypesDefinition = (RootBeanDefinition) BeanDefinitionBuilder
|
||||
.rootBeanDefinition(MyManagedTypes.class).getBeanDefinition();
|
||||
|
||||
DefaultListableBeanFactory beanFactory;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
beanFactory = new DefaultListableBeanFactory();
|
||||
}
|
||||
|
||||
@Test // GH-2593
|
||||
void processesBeanWithMatchingModulePrefix() {
|
||||
|
||||
BeanRegistrationAotContribution contribution = createPostProcessor("commons", bf -> {
|
||||
bf.registerBeanDefinition("commons.managed-types", managedTypesDefinition);
|
||||
}).contribute(managedTypesDefinition, ManagedTypes.class, "commons.managed-types");
|
||||
beanFactory.registerBeanDefinition("commons.managed-types", managedTypesDefinition);
|
||||
|
||||
BeanRegistrationAotContribution contribution = createPostProcessor("commons")
|
||||
.processAheadOfTime(RegisteredBean.of(beanFactory, "commons.managed-types"));
|
||||
|
||||
assertThat(contribution).isNotNull();
|
||||
}
|
||||
@@ -58,26 +67,27 @@ class ManagedTypesRegistrationAotProcessorUnitTests {
|
||||
@Test // GH-2593
|
||||
void contributesReflectionForManagedTypes() {
|
||||
|
||||
BeanRegistrationAotContribution contribution = createPostProcessor("commons", bf -> {
|
||||
bf.registerBeanDefinition("commons.managed-types", managedTypesDefinition);
|
||||
}).contribute(managedTypesDefinition, ManagedTypes.class, "commons.managed-types");
|
||||
beanFactory.registerBeanDefinition("commons.managed-types", managedTypesDefinition);
|
||||
|
||||
BeanRegistrationAotContribution contribution = createPostProcessor("commons")
|
||||
.processAheadOfTime(RegisteredBean.of(beanFactory, "commons.managed-types"));
|
||||
|
||||
DefaultGenerationContext generationContext = new DefaultGenerationContext(new ClassNameGenerator(),
|
||||
new InMemoryGeneratedFiles(), new RuntimeHints());
|
||||
|
||||
contribution.applyTo(generationContext, null);
|
||||
|
||||
new CodeContributionAssert(generationContext) //
|
||||
.contributesReflectionFor(A.class) //
|
||||
.doesNotContributeReflectionFor(B.class);
|
||||
assertThat(generationContext.getRuntimeHints()).matches(RuntimeHintsPredicates.reflection().onType(A.class)
|
||||
.and(RuntimeHintsPredicates.reflection().onType(B.class).negate()));
|
||||
}
|
||||
|
||||
@Test // GH-2593
|
||||
void processesMatchingSubtypeBean() {
|
||||
|
||||
BeanRegistrationAotContribution contribution = createPostProcessor("commons", bf -> {
|
||||
bf.registerBeanDefinition("commons.managed-types", myManagedTypesDefinition);
|
||||
}).contribute(myManagedTypesDefinition, MyManagedTypes.class, "commons.managed-types");
|
||||
beanFactory.registerBeanDefinition("commons.managed-types", myManagedTypesDefinition);
|
||||
|
||||
BeanRegistrationAotContribution contribution = createPostProcessor("commons")
|
||||
.processAheadOfTime(RegisteredBean.of(beanFactory, "commons.managed-types"));
|
||||
|
||||
assertThat(contribution).isNotNull();
|
||||
}
|
||||
@@ -85,9 +95,11 @@ class ManagedTypesRegistrationAotProcessorUnitTests {
|
||||
@Test // GH-2593
|
||||
void ignoresBeanNotMatchingRequiredType() {
|
||||
|
||||
BeanRegistrationAotContribution contribution = createPostProcessor("commons", bf -> {
|
||||
bf.registerBeanDefinition("commons.managed-types", managedTypesDefinition);
|
||||
}).contribute(managedTypesDefinition, Object.class, "commons.managed-types");
|
||||
beanFactory.registerBeanDefinition("commons.managed-types",
|
||||
BeanDefinitionBuilder.rootBeanDefinition(NotManagedTypes.class).getBeanDefinition());
|
||||
|
||||
BeanRegistrationAotContribution contribution = createPostProcessor("commons")
|
||||
.processAheadOfTime(RegisteredBean.of(beanFactory, "commons.managed-types"));
|
||||
|
||||
assertThat(contribution).isNull();
|
||||
}
|
||||
@@ -95,40 +107,31 @@ class ManagedTypesRegistrationAotProcessorUnitTests {
|
||||
@Test // GH-2593
|
||||
void ignoresBeanNotMatchingPrefix() {
|
||||
|
||||
BeanRegistrationAotContribution contribution = createPostProcessor("commons", bf -> {
|
||||
bf.registerBeanDefinition("commons.managed-types", managedTypesDefinition);
|
||||
}).contribute(managedTypesDefinition, ManagedTypes.class, "jpa.managed-types");
|
||||
beanFactory.registerBeanDefinition("jpa.managed-types", managedTypesDefinition);
|
||||
|
||||
BeanRegistrationAotContribution contribution = createPostProcessor("commons")
|
||||
.processAheadOfTime(RegisteredBean.of(beanFactory, "jpa.managed-types"));
|
||||
|
||||
assertThat(contribution).isNull();
|
||||
}
|
||||
|
||||
private ManagedTypesRegistrationAotProcessor createPostProcessor(String prefix, Consumer<DefaultListableBeanFactory> action) {
|
||||
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
action.accept(beanFactory);
|
||||
|
||||
ManagedTypesRegistrationAotProcessor postProcessor = createPostProcessor(beanFactory);
|
||||
postProcessor.setModulePrefix(prefix);
|
||||
private ManagedTypesBeanRegistrationAotProcessor createPostProcessor(String moduleIdentifier) {
|
||||
ManagedTypesBeanRegistrationAotProcessor postProcessor = new ManagedTypesBeanRegistrationAotProcessor();
|
||||
postProcessor.setModuleIdentifier(moduleIdentifier);
|
||||
|
||||
return postProcessor;
|
||||
}
|
||||
|
||||
private ManagedTypesRegistrationAotProcessor createPostProcessor(BeanFactory beanFactory) {
|
||||
|
||||
ManagedTypesRegistrationAotProcessor managedTypesRegistrationAotProcessor = new ManagedTypesRegistrationAotProcessor();
|
||||
managedTypesRegistrationAotProcessor.setBeanFactory(beanFactory);
|
||||
return managedTypesRegistrationAotProcessor;
|
||||
}
|
||||
|
||||
static class A {}
|
||||
|
||||
static class B {}
|
||||
|
||||
static class MyManagedTypes implements ManagedTypes {
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<Class<?>> action) {
|
||||
// just do nothing ¯\_(ツ)_/¯
|
||||
}
|
||||
}
|
||||
|
||||
static class NotManagedTypes {}
|
||||
}
|
||||
@@ -73,7 +73,7 @@ public class RepositoryRegistrationAotProcessorIntegrationTests {
|
||||
.contributesReflectionFor(ConfigWithSimpleCrudRepository.Person.class) // repository domain type
|
||||
.contributesJdkProxy(ConfigWithSimpleCrudRepository.MyRepo.class, SpringProxy.class, Advised.class,
|
||||
DecoratingProxy.class) //
|
||||
.doesNotContributeJdkProxy(ConfigWithSimpleCrudRepository.MyRepo.class, Repository.class,
|
||||
.contributesJdkProxy(ConfigWithSimpleCrudRepository.MyRepo.class, Repository.class,
|
||||
TransactionalProxy.class, Advised.class, DecoratingProxy.class)
|
||||
.doesNotContributeJdkProxy(ConfigWithSimpleCrudRepository.MyRepo.class, Repository.class,
|
||||
TransactionalProxy.class, Advised.class, DecoratingProxy.class, Serializable.class);
|
||||
|
||||
@@ -15,12 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.aot;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
@@ -31,7 +27,7 @@ import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.data.ManagedTypes;
|
||||
import org.springframework.data.domain.ManagedTypes;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
@@ -58,7 +54,7 @@ class SpringDataBeanFactoryInitializationAotProcessorUnitTests {
|
||||
|
||||
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("data.managed-types");
|
||||
|
||||
assertThat(beanDefinition.getFactoryMethodName()).isEqualTo("of");
|
||||
assertThat(beanDefinition.getFactoryMethodName()).isEqualTo("fromIterable");
|
||||
assertThat(beanDefinition.hasConstructorArgumentValues()).isTrue();
|
||||
assertThat(beanDefinition.getConstructorArgumentValues().getArgumentValue(0, null).getValue())
|
||||
.isEqualTo(Collections.singleton(DomainType.class));
|
||||
|
||||
@@ -18,6 +18,8 @@ package org.springframework.data.repository.config;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
@@ -31,6 +33,7 @@ import org.springframework.context.annotation.AnnotationBeanNameGenerator;
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
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.mapping.Person;
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.springframework.core.MethodParameter;
|
||||
*
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
class ParameterUnitTests {
|
||||
class KParameterUnitTests {
|
||||
|
||||
@Test // DATAJPA-1185
|
||||
void classParameterWithSameTypeParameterAsReturnedListIsDynamicProjectionParameter() throws Exception {
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2022 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
|
||||
*
|
||||
* https://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.util;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.classloadersupport.HidingClassLoader;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
class TypeScannerUnitTests {
|
||||
|
||||
@Test // GH-2593
|
||||
void looksForTypesMatchingAnnotationFilter() {
|
||||
|
||||
Set<Class<?>> result = TypeScanner.typeScanner(getClass().getClassLoader()) //
|
||||
.scanPackages(getClass().getPackageName()) //
|
||||
.forTypesAnnotatedWith(FindMe.class) //
|
||||
.collectAsSet();
|
||||
|
||||
assertThat(result).containsExactlyInAnyOrder(AnnotatedWithFindMe.class, AnnotatedWithMetaFindMe.class);
|
||||
}
|
||||
|
||||
@Test // GH-2593
|
||||
void looksForAllTypesIfNoFilter() {
|
||||
|
||||
Set<Class<?>> result = TypeScanner.typeScanner(getClass().getClassLoader()) //
|
||||
.scanPackages(getClass().getPackageName()) //
|
||||
.collectAsSet();
|
||||
|
||||
assertThat(result).contains(AnnotatedWithFindMe.class, AnnotatedWithMetaFindMe.class, WithoutAnnotations.class);
|
||||
}
|
||||
|
||||
@Test // GH-2593
|
||||
void ignoresClassesNotFound() {
|
||||
|
||||
TypeScanner scanner = TypeScanner.typeScanner(HidingClassLoader.hideTypes(AnnotatedWithFindMe.class)) //
|
||||
.scanPackages(getClass().getPackageName()) //
|
||||
.forTypesAnnotatedWith(FindMe.class);
|
||||
|
||||
scanner.collectAsSet(); // no exception
|
||||
}
|
||||
|
||||
@Test // GH-2593
|
||||
void raisesErrorClassesNotFoundIfConfigured() {
|
||||
|
||||
TypeScanner scanner = TypeScanner.typeScanner(HidingClassLoader.hideTypes(AnnotatedWithFindMe.class)) //
|
||||
.scanPackages(getClass().getPackageName()) //
|
||||
.forTypesAnnotatedWith(FindMe.class).onClassNotFound(ex -> {
|
||||
throw new IllegalStateException(ex);
|
||||
});
|
||||
|
||||
assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> scanner.collectAsSet()); // no exception
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface FindMe {
|
||||
}
|
||||
|
||||
@FindMe
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface MetaAnnotatedWithFindMe {
|
||||
}
|
||||
|
||||
@FindMe
|
||||
private static class AnnotatedWithFindMe {
|
||||
|
||||
}
|
||||
|
||||
@MetaAnnotatedWithFindMe
|
||||
private static class AnnotatedWithMetaFindMe {
|
||||
|
||||
}
|
||||
|
||||
private static class WithoutAnnotations {
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user