Open up AuditingBeanDefinitionRegistrarSupport.registerAuditHandlerBeanDefinition(…) to allow additional bean registrations.

Original Pull Request: #2624
This commit is contained in:
Mark Paluch
2022-06-29 09:13:35 +02:00
committed by Christoph Strobl
parent 4e23153816
commit 0a423ac3f5
30 changed files with 710 additions and 548 deletions

View File

@@ -15,7 +15,7 @@
*/
package org.springframework.data.aot;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.*;
import java.util.Arrays;
import java.util.stream.Stream;
@@ -25,19 +25,17 @@ 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
* Spring Data Repository infrastructure AOT processing.
* AssertJ {@link AbstractAssert Assertion} for code contributions originating from Spring Data Repository
* infrastructure AOT processing.
*
* @author Christoph Strobl
* @author John Blum
* @see org.assertj.core.api.AbstractAssert
* @see org.springframework.aot.generate.GenerationContext
* @since 3.0.0
* @since 3.0
*/
@SuppressWarnings("UnusedReturnValue")
public class CodeContributionAssert extends AbstractAssert<CodeContributionAssert, GenerationContext> {
public CodeContributionAssert(GenerationContext contribution) {
@@ -47,8 +45,7 @@ public class CodeContributionAssert extends AbstractAssert<CodeContributionAsser
public CodeContributionAssert contributesReflectionFor(Class<?>... types) {
for (Class<?> type : types) {
assertThat(this.actual.getRuntimeHints())
.describedAs("No reflection entry found for [%s]", type)
assertThat(this.actual.getRuntimeHints()).describedAs("No reflection entry found for [%s]", type)
.matches(RuntimeHintsPredicates.reflection().onType(type));
}
@@ -58,8 +55,7 @@ public class CodeContributionAssert extends AbstractAssert<CodeContributionAsser
public CodeContributionAssert doesNotContributeReflectionFor(Class<?>... types) {
for (Class<?> type : types) {
assertThat(this.actual.getRuntimeHints())
.describedAs("Reflection entry found for [%s]", type)
assertThat(this.actual.getRuntimeHints()).describedAs("Reflection entry found for [%s]", type)
.matches(RuntimeHintsPredicates.reflection().onType(type).negate());
}
@@ -68,8 +64,7 @@ public class CodeContributionAssert extends AbstractAssert<CodeContributionAsser
public CodeContributionAssert contributesJdkProxyFor(Class<?> entryPoint) {
assertThat(jdkProxiesFor(entryPoint).findFirst())
.describedAs("No JDK proxy found for [%s]", entryPoint)
assertThat(jdkProxiesFor(entryPoint).findFirst()).describedAs("No JDK proxy found for [%s]", entryPoint)
.isPresent();
return this;
@@ -78,8 +73,7 @@ public class CodeContributionAssert extends AbstractAssert<CodeContributionAsser
public CodeContributionAssert doesNotContributeJdkProxyFor(Class<?> entryPoint) {
assertThat(jdkProxiesFor(entryPoint).findFirst())
.describedAs("Found JDK proxy matching [%s] though it should not be present", entryPoint)
.isNotPresent();
.describedAs("Found JDK proxy matching [%s] though it should not be present", entryPoint).isNotPresent();
return this;
}
@@ -87,8 +81,8 @@ public class CodeContributionAssert extends AbstractAssert<CodeContributionAsser
public CodeContributionAssert contributesJdkProxy(Class<?>... proxyInterfaces) {
assertThat(jdkProxiesFor(proxyInterfaces[0]))
.describedAs("Unable to find JDK proxy matching [%s]", Arrays.asList(proxyInterfaces))
.anySatisfy(it -> new JdkProxyAssert(it).matches(proxyInterfaces));
.describedAs("Unable to find JDK proxy matching [%s]", Arrays.asList(proxyInterfaces))
.anySatisfy(it -> new JdkProxyAssert(it).matches(proxyInterfaces));
return this;
}
@@ -96,8 +90,7 @@ public class CodeContributionAssert extends AbstractAssert<CodeContributionAsser
public CodeContributionAssert doesNotContributeJdkProxy(Class<?>... proxyInterfaces) {
assertThat(jdkProxiesFor(proxyInterfaces[0]))
.describedAs("Found JDK proxy matching [%s] though it should not be present",
Arrays.asList(proxyInterfaces))
.describedAs("Found JDK proxy matching [%s] though it should not be present", Arrays.asList(proxyInterfaces))
.noneSatisfy(it -> new JdkProxyAssert(it).matches(proxyInterfaces));
return this;
@@ -105,9 +98,8 @@ public class CodeContributionAssert extends AbstractAssert<CodeContributionAsser
private Stream<JdkProxyHint> jdkProxiesFor(Class<?> entryPoint) {
return this.actual.getRuntimeHints().proxies().jdkProxies()
.filter(jdkProxyHint -> jdkProxyHint.getProxiedInterfaces().get(0).getCanonicalName()
.equals(entryPoint.getCanonicalName()));
return this.actual.getRuntimeHints().proxies().jdkProxies().filter(jdkProxyHint -> jdkProxyHint
.getProxiedInterfaces().get(0).getCanonicalName().equals(entryPoint.getCanonicalName()));
}
public CodeContributionAssert contributesClassProxy(Class<?>... proxyInterfaces) {
@@ -121,8 +113,7 @@ public class CodeContributionAssert extends AbstractAssert<CodeContributionAsser
private Stream<ClassProxyHint> classProxiesFor(Class<?> entryPoint) {
return this.actual.getRuntimeHints().proxies().classProxies()
.filter(jdkProxyHint -> jdkProxyHint.getProxiedInterfaces().get(0).getCanonicalName()
.equals(entryPoint.getCanonicalName()));
return this.actual.getRuntimeHints().proxies().classProxies().filter(jdkProxyHint -> jdkProxyHint
.getProxiedInterfaces().get(0).getCanonicalName().equals(entryPoint.getCanonicalName()));
}
}

View File

@@ -26,7 +26,6 @@ import org.springframework.aot.hint.TypeReference;
/**
* @author Christoph Strobl
* @since 2022/04
*/
public class JdkProxyAssert extends AbstractAssert<JdkProxyAssert, JdkProxyHint> {

View File

@@ -24,6 +24,7 @@ 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.GeneratedClasses;
import org.springframework.aot.generate.InMemoryGeneratedFiles;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsPredicates;
@@ -72,7 +73,8 @@ class ManagedTypesBeanRegistrationAotProcessorUnitTests {
BeanRegistrationAotContribution contribution = createPostProcessor("commons")
.processAheadOfTime(RegisteredBean.of(beanFactory, "commons.managed-types"));
DefaultGenerationContext generationContext = new DefaultGenerationContext(new ClassNameGenerator(),
DefaultGenerationContext generationContext = new DefaultGenerationContext(
new GeneratedClasses(new ClassNameGenerator(Object.class)),
new InMemoryGeneratedFiles(), new RuntimeHints());
contribution.applyTo(generationContext, null);

View File

@@ -15,8 +15,8 @@
*/
package org.springframework.data.aot;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import java.util.LinkedHashSet;
import java.util.Set;
@@ -27,36 +27,41 @@ import org.assertj.core.api.AbstractAssert;
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.aot.BeanRegistrationCode;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.support.RepositoryFragment;
import org.springframework.lang.NonNull;
/**
* AssertJ {@link AbstractAssert Assertion} for {@link RepositoryRegistrationAotContribution}.
*
* @author Christoph Strobl
* @author John Blum
* @see org.mockito.Mockito
* @see org.assertj.core.api.AbstractAssert
* @see org.springframework.data.aot.RepositoryRegistrationAotContribution
* @since 3.0.0
* @since 3.0
*/
public class RepositoryRegistrationAotContributionAssert
extends AbstractAssert<RepositoryRegistrationAotContributionAssert, RepositoryRegistrationAotContribution> {
extends AbstractAssert<RepositoryRegistrationAotContributionAssert, RepositoryRegistrationAotContribution> {
@NonNull
public static RepositoryRegistrationAotContributionAssert assertThatContribution(
@NonNull RepositoryRegistrationAotContribution actual) {
RepositoryRegistrationAotContribution actual) {
return new RepositoryRegistrationAotContributionAssert(actual);
}
public RepositoryRegistrationAotContributionAssert(@NonNull RepositoryRegistrationAotContribution actual) {
/**
* Create the assertion object.
*
* @param actual
*/
public RepositoryRegistrationAotContributionAssert(RepositoryRegistrationAotContribution actual) {
super(actual, RepositoryRegistrationAotContributionAssert.class);
}
/**
* Verifies that the actual repository type is equal to the given one.
*
* @param expected
* @return {@code this} assertion object.
*/
public RepositoryRegistrationAotContributionAssert targetRepositoryTypeIs(Class<?> expected) {
assertThat(getRepositoryInformation().getRepositoryInterface()).isEqualTo(expected);
@@ -64,6 +69,11 @@ public class RepositoryRegistrationAotContributionAssert
return this.myself;
}
/**
* Verifies that the actual repository has no repository fragments.
*
* @return {@code this} assertion object.
*/
public RepositoryRegistrationAotContributionAssert hasNoFragments() {
assertThat(getRepositoryInformation().getFragments()).isEmpty();
@@ -71,6 +81,11 @@ public class RepositoryRegistrationAotContributionAssert
return this;
}
/**
* Verifies that the actual repository has repository fragments.
*
* @return {@code this} assertion object.
*/
public RepositoryRegistrationAotContributionAssert hasFragments() {
assertThat(getRepositoryInformation().getFragments()).isNotEmpty();
@@ -78,10 +93,14 @@ public class RepositoryRegistrationAotContributionAssert
return this;
}
/**
* Verifies that the actual repository fragments satisfy the given {@link Consumer}.
*
* @return {@code this} assertion object.
*/
public RepositoryRegistrationAotContributionAssert verifyFragments(Consumer<Set<RepositoryFragment<?>>> consumer) {
assertThat(getRepositoryInformation().getFragments())
.satisfies(it -> consumer.accept(new LinkedHashSet<>(it)));
assertThat(getRepositoryInformation().getFragments()).satisfies(it -> consumer.accept(new LinkedHashSet<>(it)));
return this;
}
@@ -91,8 +110,8 @@ public class RepositoryRegistrationAotContributionAssert
BeanRegistrationCode mockBeanRegistrationCode = mock(BeanRegistrationCode.class);
DefaultGenerationContext generationContext =
new DefaultGenerationContext(new ClassNameGenerator(), new InMemoryGeneratedFiles(), new RuntimeHints());
DefaultGenerationContext generationContext = new DefaultGenerationContext(new ClassNameGenerator(Object.class),
new InMemoryGeneratedFiles());
this.actual.applyTo(generationContext, mockBeanRegistrationCode);
@@ -103,13 +122,10 @@ public class RepositoryRegistrationAotContributionAssert
private RepositoryInformation getRepositoryInformation() {
assertThat(this.actual)
.describedAs("No repository interface found on null bean contribution")
.isNotNull();
assertThat(this.actual).describedAs("No repository interface found on null bean contribution").isNotNull();
assertThat(this.actual.getRepositoryInformation())
.describedAs("No repository interface found on null repository information")
.isNotNull();
.describedAs("No repository interface found on null repository information").isNotNull();
return this.actual.getRepositoryInformation();
}

View File

@@ -15,8 +15,8 @@
*/
package org.springframework.data.aot;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.data.aot.RepositoryRegistrationAotContributionAssert.assertThatContribution;
import static org.assertj.core.api.Assertions.*;
import static org.springframework.data.aot.RepositoryRegistrationAotContributionAssert.*;
import java.io.Serializable;
@@ -51,9 +51,6 @@ import org.springframework.transaction.interceptor.TransactionalProxy;
* Integration Tests for {@link RepositoryRegistrationAotProcessor}.
*
* @author Christoph Strobl
* @see org.junit.jupiter.api.Test
* @see org.springframework.data.aot.RepositoryRegistrationAotProcessor
* @see org.springframework.data.aot.RepositoryRegistrationAotContributionAssert
* @author John Blum
*/
public class RepositoryRegistrationAotProcessorIntegrationTests {
@@ -61,8 +58,8 @@ public class RepositoryRegistrationAotProcessorIntegrationTests {
@Test // GH-2593
void simpleRepositoryNoTxManagerNoKotlinNoReactiveNoComponent() {
RepositoryRegistrationAotContribution repositoryBeanContribution = computeAotConfiguration(ConfigWithSimpleCrudRepository.class)
.forRepository(ConfigWithSimpleCrudRepository.MyRepo.class);
RepositoryRegistrationAotContribution repositoryBeanContribution = computeAotConfiguration(
ConfigWithSimpleCrudRepository.class).forRepository(ConfigWithSimpleCrudRepository.MyRepo.class);
assertThatContribution(repositoryBeanContribution) //
.targetRepositoryTypeIs(ConfigWithSimpleCrudRepository.MyRepo.class) //
@@ -123,8 +120,7 @@ public class RepositoryRegistrationAotProcessorIntegrationTests {
// interface
.contributesReflectionFor(PagingAndSortingRepository.class) // base repository
.contributesReflectionFor(
ConfigWithTransactionManagerPresentAndAtComponentAnnotatedRepoisoty.Person.class) // repository domain
// type
ConfigWithTransactionManagerPresentAndAtComponentAnnotatedRepoisoty.Person.class) // domain type
// proxies
.contributesJdkProxy(
@@ -142,8 +138,8 @@ public class RepositoryRegistrationAotProcessorIntegrationTests {
@Test // GH-2593
void contributesFragmentsCorrectly() {
RepositoryRegistrationAotContribution repositoryBeanContribution = computeAotConfiguration(ConfigWithFragments.class)
.forRepository(ConfigWithFragments.RepositoryWithFragments.class);
RepositoryRegistrationAotContribution repositoryBeanContribution = computeAotConfiguration(
ConfigWithFragments.class).forRepository(ConfigWithFragments.RepositoryWithFragments.class);
assertThatContribution(repositoryBeanContribution) //
.targetRepositoryTypeIs(ConfigWithFragments.RepositoryWithFragments.class) //
@@ -175,8 +171,9 @@ public class RepositoryRegistrationAotProcessorIntegrationTests {
@Test // GH-2593
void contributesCustomImplementationCorrectly() {
RepositoryRegistrationAotContribution repositoryBeanContribution = computeAotConfiguration(ConfigWithCustomImplementation.class)
.forRepository(ConfigWithCustomImplementation.RepositoryWithCustomImplementation.class);
RepositoryRegistrationAotContribution repositoryBeanContribution = computeAotConfiguration(
ConfigWithCustomImplementation.class)
.forRepository(ConfigWithCustomImplementation.RepositoryWithCustomImplementation.class);
assertThatContribution(repositoryBeanContribution) //
.targetRepositoryTypeIs(ConfigWithCustomImplementation.RepositoryWithCustomImplementation.class) //
@@ -197,12 +194,11 @@ public class RepositoryRegistrationAotProcessorIntegrationTests {
@Test // GH-2593
void contributesDomainTypeAndReachableTypesCorrectly() {
RepositoryRegistrationAotContribution repositoryBeanContribution =
computeAotConfiguration(ConfigWithSimpleCrudRepository.class)
.forRepository(ConfigWithSimpleCrudRepository.MyRepo.class);
RepositoryRegistrationAotContribution repositoryBeanContribution = computeAotConfiguration(
ConfigWithSimpleCrudRepository.class).forRepository(ConfigWithSimpleCrudRepository.MyRepo.class);
assertThatContribution(repositoryBeanContribution).codeContributionSatisfies(contribution ->
contribution.contributesReflectionFor(ConfigWithSimpleCrudRepository.Person.class,
assertThatContribution(repositoryBeanContribution).codeContributionSatisfies(
contribution -> contribution.contributesReflectionFor(ConfigWithSimpleCrudRepository.Person.class,
ConfigWithSimpleCrudRepository.Address.class));
}
@@ -245,19 +241,18 @@ public class RepositoryRegistrationAotProcessorIntegrationTests {
@Test // GH-2593
void contributesTypesFromQueryMethods() {
RepositoryRegistrationAotContribution repositoryBeanContribution = computeAotConfiguration(ConfigWithQueryMethods.class)
.forRepository(ConfigWithQueryMethods.CustomerRepositoryWithQueryMethods.class);
RepositoryRegistrationAotContribution repositoryBeanContribution = computeAotConfiguration(
ConfigWithQueryMethods.class).forRepository(ConfigWithQueryMethods.CustomerRepositoryWithQueryMethods.class);
assertThatContribution(repositoryBeanContribution)
.codeContributionSatisfies(contribution ->
contribution.contributesReflectionFor(ProjectionInterface.class));
.codeContributionSatisfies(contribution -> contribution.contributesReflectionFor(ProjectionInterface.class));
}
@Test // GH-2593
void contributesProxiesForPotentialProjections() {
RepositoryRegistrationAotContribution repositoryBeanContribution = computeAotConfiguration(ConfigWithQueryMethods.class)
.forRepository(ConfigWithQueryMethods.CustomerRepositoryWithQueryMethods.class);
RepositoryRegistrationAotContribution repositoryBeanContribution = computeAotConfiguration(
ConfigWithQueryMethods.class).forRepository(ConfigWithQueryMethods.CustomerRepositoryWithQueryMethods.class);
assertThatContribution(repositoryBeanContribution) //
.codeContributionSatisfies(contribution -> {
@@ -271,8 +266,8 @@ public class RepositoryRegistrationAotProcessorIntegrationTests {
@Test // GH-2593
void contributesProxiesForDataAnnotations() {
RepositoryRegistrationAotContribution repositoryBeanContribution = computeAotConfiguration(ConfigWithQueryMethods.class)
.forRepository(ConfigWithQueryMethods.CustomerRepositoryWithQueryMethods.class);
RepositoryRegistrationAotContribution repositoryBeanContribution = computeAotConfiguration(
ConfigWithQueryMethods.class).forRepository(ConfigWithQueryMethods.CustomerRepositoryWithQueryMethods.class);
assertThatContribution(repositoryBeanContribution) //
.codeContributionSatisfies(contribution -> {
@@ -286,8 +281,8 @@ public class RepositoryRegistrationAotProcessorIntegrationTests {
@Test // GH-2593
void doesNotCareAboutNonDataAnnotations() {
RepositoryRegistrationAotContribution repositoryBeanContribution = computeAotConfiguration(ConfigWithSimpleCrudRepository.class)
.forRepository(ConfigWithSimpleCrudRepository.MyRepo.class);
RepositoryRegistrationAotContribution repositoryBeanContribution = computeAotConfiguration(
ConfigWithSimpleCrudRepository.class).forRepository(ConfigWithSimpleCrudRepository.MyRepo.class);
assertThatContribution(repositoryBeanContribution) //
.codeContributionSatisfies(contribution -> {
@@ -311,16 +306,15 @@ public class RepositoryRegistrationAotProcessorIntegrationTests {
String[] repositoryBeanNames = applicationContext.getBeanNamesForType(repositoryType);
assertThat(repositoryBeanNames)
.describedAs("Unable to find repository [%s] in configuration [%s]",
repositoryType, configuration)
.describedAs("Unable to find repository [%s] in configuration [%s]", repositoryType, configuration)
.hasSize(1);
String repositoryBeanName = repositoryBeanNames[0];
ConfigurableBeanFactory beanFactory = applicationContext.getDefaultListableBeanFactory();
RepositoryRegistrationAotProcessor repositoryAotProcessor =
applicationContext.getBean(RepositoryRegistrationAotProcessor.class);
RepositoryRegistrationAotProcessor repositoryAotProcessor = applicationContext
.getBean(RepositoryRegistrationAotProcessor.class);
repositoryAotProcessor.setBeanFactory(beanFactory);

View File

@@ -25,6 +25,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
import org.springframework.aop.framework.Advised;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
@@ -67,7 +68,7 @@ class RepositoryConfigurationDelegateUnitTests {
var beanDefinition = definition.getBeanDefinition();
assertThat(beanDefinition.getAttribute(RepositoryConfigurationDelegate.FACTORY_BEAN_OBJECT_TYPE).toString())
assertThat(beanDefinition.getAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE).toString())
.endsWith("Repository");
}
}