From 6bc28c118cb242d05363acc42a8f9857d66acbae Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 2 Mar 2022 14:22:30 +0100 Subject: [PATCH] Consider annotated methods in AnnotationRevisionMetadata. We now detect annotated methods. Closes #2569 --- .../history/AnnotationRevisionMetadata.java | 12 ++++++- .../AnnotationDetectionMethodCallback.java | 4 +++ .../AnnotationRevisionMetadataUnitTests.java | 32 +++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/springframework/data/history/AnnotationRevisionMetadata.java b/src/main/java/org/springframework/data/history/AnnotationRevisionMetadata.java index a9d96cb1c..9829d571e 100755 --- a/src/main/java/org/springframework/data/history/AnnotationRevisionMetadata.java +++ b/src/main/java/org/springframework/data/history/AnnotationRevisionMetadata.java @@ -23,6 +23,7 @@ import java.util.Date; import java.util.Optional; import org.springframework.data.util.AnnotationDetectionFieldCallback; +import org.springframework.data.util.AnnotationDetectionMethodCallback; import org.springframework.data.util.Lazy; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; @@ -34,6 +35,7 @@ import org.springframework.util.ReflectionUtils; * * @author Oliver Gierke * @author Jens Schauder + * @author Mark Paluch */ public class AnnotationRevisionMetadata> implements RevisionMetadata { @@ -98,11 +100,19 @@ public class AnnotationRevisionMetadata> implem return (T) entity; } + @SuppressWarnings("unchecked") private static Lazy> detectAnnotation(Object entity, Class annotationType) { return Lazy.of(() -> { - var callback = new AnnotationDetectionFieldCallback(annotationType); + AnnotationDetectionMethodCallback methodCallback = new AnnotationDetectionMethodCallback<>( + annotationType); + ReflectionUtils.doWithMethods(entity.getClass(), methodCallback); + if (methodCallback.getMethod() != null) { + return Optional.ofNullable((T) ReflectionUtils.invokeMethod(methodCallback.getRequiredMethod(), entity)); + } + + AnnotationDetectionFieldCallback callback = new AnnotationDetectionFieldCallback(annotationType); ReflectionUtils.doWithFields(entity.getClass(), callback); return Optional.ofNullable(callback.getValue(entity)); }); diff --git a/src/main/java/org/springframework/data/util/AnnotationDetectionMethodCallback.java b/src/main/java/org/springframework/data/util/AnnotationDetectionMethodCallback.java index 0cb3957d0..402179350 100644 --- a/src/main/java/org/springframework/data/util/AnnotationDetectionMethodCallback.java +++ b/src/main/java/org/springframework/data/util/AnnotationDetectionMethodCallback.java @@ -21,6 +21,7 @@ import java.lang.reflect.Method; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils.MethodCallback; /** @@ -28,6 +29,7 @@ import org.springframework.util.ReflectionUtils.MethodCallback; * * @author Oliver Gierke * @author Christoph Strobl + * @author Mark Paluch */ public class AnnotationDetectionMethodCallback implements MethodCallback { @@ -121,6 +123,8 @@ public class AnnotationDetectionMethodCallback implements } this.annotation = foundAnnotation; + + ReflectionUtils.makeAccessible(method); this.foundMethod = method; } } diff --git a/src/test/java/org/springframework/data/history/AnnotationRevisionMetadataUnitTests.java b/src/test/java/org/springframework/data/history/AnnotationRevisionMetadataUnitTests.java index cb8775c39..5f0a9a9ed 100644 --- a/src/test/java/org/springframework/data/history/AnnotationRevisionMetadataUnitTests.java +++ b/src/test/java/org/springframework/data/history/AnnotationRevisionMetadataUnitTests.java @@ -33,6 +33,7 @@ import org.springframework.data.annotation.Reference; * * @author Oliver Gierke * @author Jens Schauder + * @author Mark Paluch */ class AnnotationRevisionMetadataUnitTests { @@ -83,6 +84,21 @@ class AnnotationRevisionMetadataUnitTests { softly.assertAll(); } + @Test // GH-2569 + void exposesRevisionMetadataUsingMethodAccessors() { + + SampleWithMethodAnnotations sample = new SampleWithMethodAnnotations(); + sample.revisionNumber = 1L; + sample.revisionDate = Instant.now(); + + RevisionMetadata metadata = getMetadata(sample); + + softly.assertThat(metadata.getRevisionNumber()).hasValue(1L); + softly.assertThat(metadata.getRevisionInstant()).hasValue(sample.revisionDate); + + softly.assertAll(); + } + @Test // DATACMNS-1251 void exposesRevisionDateAndInstantForInstant() { @@ -149,6 +165,22 @@ class AnnotationRevisionMetadataUnitTests { @Reference LocalDateTime revisionDate; } + static class SampleWithMethodAnnotations { + + Long revisionNumber; + Instant revisionDate; + + @Autowired + public Long getRevisionNumber() { + return revisionNumber; + } + + @Reference + public Instant getRevisionDate() { + return revisionDate; + } + } + static class SampleWithInstant { @Autowired Long revisionNumber;