From a9a409813573673c45ccb58e35803286df37dbde Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Thu, 23 Oct 2025 10:36:56 +0200 Subject: [PATCH] Register domain event handling methods on AbstractAggregateRoot for native reflection. --- .../aot/hint/RepositoryRuntimeHints.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/main/java/org/springframework/data/repository/aot/hint/RepositoryRuntimeHints.java b/src/main/java/org/springframework/data/repository/aot/hint/RepositoryRuntimeHints.java index 7a32dd2809..690be55f97 100644 --- a/src/main/java/org/springframework/data/repository/aot/hint/RepositoryRuntimeHints.java +++ b/src/main/java/org/springframework/data/repository/aot/hint/RepositoryRuntimeHints.java @@ -15,20 +15,28 @@ */ package org.springframework.data.repository.aot.hint; +import java.lang.annotation.Annotation; import java.util.Arrays; +import java.util.Collection; +import java.util.List; import java.util.Properties; import org.jspecify.annotations.Nullable; import org.springframework.aop.SpringProxy; import org.springframework.aop.framework.Advised; +import org.springframework.aot.hint.ExecutableMode; import org.springframework.aot.hint.MemberCategory; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.RuntimeHintsRegistrar; import org.springframework.aot.hint.TypeReference; import org.springframework.beans.factory.BeanFactory; import org.springframework.core.DecoratingProxy; +import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.core.io.InputStreamSource; +import org.springframework.data.domain.AbstractAggregateRoot; +import org.springframework.data.domain.AfterDomainEventPublication; +import org.springframework.data.domain.DomainEvents; import org.springframework.data.domain.Example; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.repository.core.RepositoryMetadata; @@ -42,6 +50,7 @@ import org.springframework.data.repository.query.QueryByExampleExecutor; import org.springframework.data.repository.query.ReactiveQueryByExampleExecutor; import org.springframework.data.util.ReactiveWrappers; +import org.springframework.util.ReflectionUtils; /** * {@link RuntimeHintsRegistrar} holding required hints to bootstrap data repositories.
@@ -49,10 +58,14 @@ * * @author Christoph Strobl * @author Mark Paluch + * @author Oliver Drotbohm * @since 3.0 */ class RepositoryRuntimeHints implements RuntimeHintsRegistrar { + private static final Collection> DOMAIN_EVENT_ANNOTATIONS = List + .of(AfterDomainEventPublication.class, DomainEvents.class); + @Override public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) { @@ -72,6 +85,17 @@ public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) builder.withMembers(MemberCategory.INVOKE_PUBLIC_METHODS); }); + // Register event handling methods on AbstractAggregateRoot for reflection + ReflectionUtils.doWithLocalMethods(AbstractAggregateRoot.class, method -> { + + DOMAIN_EVENT_ANNOTATIONS.forEach(it -> { + + if (AnnotatedElementUtils.isAnnotated(method, it)) { + hints.reflection().registerMethod(method, ExecutableMode.INVOKE); + } + }); + }); + if (ReactiveWrappers.PROJECT_REACTOR_PRESENT) { // repository infrastructure