Skip to content

Commit 79ed0a7

Browse files
mp911dechristophstrobl
authored andcommitted
Support @value meta-annotations and expose MergedAnnotations on PreferredConstructor parameters.
We now support composed annotation that are annotated with `@Value`. we also expose MergedAnnotations through PreferredConstructor.Parameter for further use by store modules that want to inspect constructor argument annotations. Closes: #2332 Original Pull Request: #2333
1 parent 9224710 commit 79ed0a7

File tree

2 files changed

+49
-6
lines changed

2 files changed

+49
-6
lines changed

src/main/java/org/springframework/data/mapping/PreferredConstructor.java

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.util.concurrent.ConcurrentHashMap;
2424

2525
import org.springframework.beans.factory.annotation.Value;
26+
import org.springframework.core.annotation.MergedAnnotations;
2627
import org.springframework.data.annotation.PersistenceConstructor;
2728
import org.springframework.data.util.Lazy;
2829
import org.springframework.data.util.TypeInformation;
@@ -175,6 +176,7 @@ public static class Parameter<T, P extends PersistentProperty<P>> {
175176

176177
private final @Nullable String name;
177178
private final TypeInformation<T> type;
179+
private final MergedAnnotations annotations;
178180
private final String key;
179181
private final @Nullable PersistentEntity<T, P> entity;
180182

@@ -199,7 +201,8 @@ public Parameter(@Nullable String name, TypeInformation<T> type, Annotation[] an
199201

200202
this.name = name;
201203
this.type = type;
202-
this.key = getValue(annotations);
204+
this.annotations = MergedAnnotations.from(annotations);
205+
this.key = getValue(this.annotations);
203206
this.entity = entity;
204207

205208
this.enclosingClassCache = Lazy.of(() -> {
@@ -216,12 +219,12 @@ public Parameter(@Nullable String name, TypeInformation<T> type, Annotation[] an
216219
}
217220

218221
@Nullable
219-
private static String getValue(Annotation[] annotations) {
222+
private static String getValue(MergedAnnotations annotations) {
220223

221-
return Arrays.stream(annotations)//
222-
.filter(it -> it.annotationType() == Value.class)//
223-
.findFirst().map(it -> ((Value) it).value())//
224-
.filter(StringUtils::hasText).orElse(null);
224+
return annotations.get(Value.class) //
225+
.getValue("value", String.class) //
226+
.filter(StringUtils::hasText) //
227+
.orElse(null);
225228
}
226229

227230
/**
@@ -243,6 +246,16 @@ public TypeInformation<T> getType() {
243246
return type;
244247
}
245248

249+
/**
250+
* Merged annotations that this parameter is annotated with.
251+
*
252+
* @return
253+
* @since 2.5
254+
*/
255+
public MergedAnnotations getAnnotations() {
256+
return annotations;
257+
}
258+
246259
/**
247260
* Returns the raw resolved type of the parameter.
248261
*

src/test/java/org/springframework/data/mapping/PreferredConstructorDiscovererUnitTests.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,15 @@
1717

1818
import static org.assertj.core.api.Assertions.*;
1919

20+
import java.lang.annotation.ElementType;
21+
import java.lang.annotation.Retention;
22+
import java.lang.annotation.RetentionPolicy;
23+
import java.lang.annotation.Target;
2024
import java.util.Iterator;
2125

2226
import org.junit.jupiter.api.Test;
27+
28+
import org.springframework.beans.factory.annotation.Value;
2329
import org.springframework.data.annotation.PersistenceConstructor;
2430
import org.springframework.data.mapping.PreferredConstructor.Parameter;
2531
import org.springframework.data.mapping.PreferredConstructorDiscovererUnitTests.Outer.Inner;
@@ -135,6 +141,16 @@ void capturesSuperClassEnclosingTypeParameterOfNonStaticInnerClass() {
135141
});
136142
}
137143

144+
@Test // GH-2332
145+
void detectsMetaAnnotatedValueAnnotation() {
146+
147+
assertThat(PreferredConstructorDiscoverer.discover(ClassWithMetaAnnotatedParameter.class)).satisfies(ctor -> {
148+
149+
assertThat(ctor.getParameters().get(0).getSpelExpression()).isEqualTo("${hello-world}");
150+
assertThat(ctor.getParameters().get(0).getAnnotations()).isNotNull();
151+
});
152+
}
153+
138154
static class SyntheticConstructor {
139155
@PersistenceConstructor
140156
private SyntheticConstructor(String x) {}
@@ -204,4 +220,18 @@ public NonStaticInnerWithGenericArgUsedInCtor(T value) {
204220
super(value);
205221
}
206222
}
223+
224+
static class ClassWithMetaAnnotatedParameter {
225+
226+
ClassWithMetaAnnotatedParameter(@MyValue String value) {
227+
228+
}
229+
}
230+
231+
@Target({ ElementType.PARAMETER, })
232+
@Retention(RetentionPolicy.RUNTIME)
233+
@Value("${hello-world}")
234+
@interface MyValue {
235+
236+
}
207237
}

0 commit comments

Comments
 (0)