diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/RepositoryRuntimeHints.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/RepositoryRuntimeHints.java index d9d011827..000a5b3ef 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/RepositoryRuntimeHints.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/RepositoryRuntimeHints.java @@ -24,10 +24,12 @@ import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.RuntimeHintsRegistrar; import org.springframework.aot.hint.TypeReference; import org.springframework.data.mongodb.aot.MongoAotPredicates; +import org.springframework.data.mongodb.repository.support.CrudMethodMetadata; import org.springframework.data.mongodb.repository.support.QuerydslMongoPredicateExecutor; import org.springframework.data.mongodb.repository.support.ReactiveQuerydslMongoPredicateExecutor; import org.springframework.data.querydsl.QuerydslUtils; import org.springframework.lang.Nullable; +import org.springframework.util.ClassUtils; /** * @author Christoph Strobl @@ -43,6 +45,15 @@ class RepositoryRuntimeHints implements RuntimeHintsRegistrar { builder -> builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS)); + if (isAopPresent(classLoader)) { + + // required for pushing ReadPreference,... into the default repository implementation + hints.proxies().registerJdkProxy(CrudMethodMetadata.class, // + org.springframework.aop.SpringProxy.class, // + org.springframework.aop.framework.Advised.class, // + org.springframework.core.DecoratingProxy.class); + } + if (isReactorPresent()) { hints.reflection().registerTypes( @@ -77,4 +88,8 @@ class RepositoryRuntimeHints implements RuntimeHintsRegistrar { MemberCategory.INVOKE_DECLARED_CONSTRUCTORS); } } + + private static boolean isAopPresent(@Nullable ClassLoader classLoader) { + return ClassUtils.isPresent("org.springframework.aop.Pointcut", classLoader); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/aot/RepositoryRuntimeHintsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/aot/RepositoryRuntimeHintsUnitTests.java index 59e1f20e9..c3a67ddbc 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/aot/RepositoryRuntimeHintsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/aot/RepositoryRuntimeHintsUnitTests.java @@ -22,6 +22,7 @@ import org.junit.jupiter.api.Test; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; import org.springframework.data.mongodb.classloading.HidingClassLoader; +import org.springframework.data.mongodb.repository.support.CrudMethodMetadata; import org.springframework.data.mongodb.repository.support.QuerydslMongoPredicateExecutor; import org.springframework.data.mongodb.repository.support.ReactiveQuerydslMongoPredicateExecutor; @@ -64,4 +65,16 @@ class RepositoryRuntimeHintsUnitTests { assertThat(runtimeHints).matches(RuntimeHintsPredicates.reflection().onType(QuerydslMongoPredicateExecutor.class) .and(RuntimeHintsPredicates.reflection().onType(ReactiveQuerydslMongoPredicateExecutor.class).negate())); } + + @Test // GH-2971, GH-4534 + void registersProxyForCrudMethodMetadata() { + + RuntimeHints runtimeHints = new RuntimeHints(); + new RepositoryRuntimeHints().registerHints(runtimeHints, null); + + assertThat(runtimeHints).matches(RuntimeHintsPredicates.proxies().forInterfaces(CrudMethodMetadata.class, // + org.springframework.aop.SpringProxy.class, // + org.springframework.aop.framework.Advised.class, // + org.springframework.core.DecoratingProxy.class)); + } }