Browse Source
Add a factory method to `MergedAnnotation` that allows an instance to be created for an explicit collection of root annotations. This method will allow ASM based readers to expose a `MergedAnnotation` instance that has root annotations loaded from bytecode, and meta-annotations loaded using reflection. See gh-22884pull/25019/head
Phillip Webb
6 years ago
committed by
Juergen Hoeller
4 changed files with 652 additions and 1 deletions
@ -0,0 +1,315 @@
@@ -0,0 +1,315 @@
|
||||
/* |
||||
* Copyright 2002-2019 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.annotation; |
||||
|
||||
import java.lang.annotation.Annotation; |
||||
import java.util.Collection; |
||||
import java.util.Iterator; |
||||
import java.util.Spliterator; |
||||
import java.util.Spliterators; |
||||
import java.util.function.Consumer; |
||||
import java.util.function.Predicate; |
||||
import java.util.stream.Stream; |
||||
import java.util.stream.StreamSupport; |
||||
|
||||
import org.springframework.lang.Nullable; |
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* {@link MergedAnnotations} implementation backed by a {@link Collection} |
||||
* {@link MergedAnnotation} instances that represent direct annotations. |
||||
* |
||||
* @author Phillip Webb |
||||
* @since 5.2 |
||||
* @see MergedAnnotations#of(Collection) |
||||
*/ |
||||
final class MergedAnnotationsCollection implements MergedAnnotations { |
||||
|
||||
private final MergedAnnotation<?>[] annotations; |
||||
|
||||
private final AnnotationTypeMappings[] mappings; |
||||
|
||||
private MergedAnnotationsCollection(Collection<MergedAnnotation<?>> annotations) { |
||||
Assert.notNull(annotations, "Annotations must not be null"); |
||||
this.annotations = annotations.toArray(new MergedAnnotation<?>[0]); |
||||
this.mappings = new AnnotationTypeMappings[this.annotations.length]; |
||||
for (int i = 0; i < this.annotations.length; i++) { |
||||
MergedAnnotation<?> annotation = this.annotations[i]; |
||||
Assert.notNull(annotation, "Annotation must not be null"); |
||||
Assert.isTrue(annotation.isDirectlyPresent(), "Annotation must be directly present"); |
||||
Assert.isTrue(annotation.getAggregateIndex() == 0, "Annotation must have aggregate index of zero"); |
||||
this.mappings[i] = AnnotationTypeMappings.forAnnotationType( |
||||
annotation.getType()); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public Iterator<MergedAnnotation<Annotation>> iterator() { |
||||
return Spliterators.iterator(spliterator()); |
||||
} |
||||
|
||||
@Override |
||||
public Spliterator<MergedAnnotation<Annotation>> spliterator() { |
||||
return spliterator(null); |
||||
} |
||||
|
||||
private <A extends Annotation> Spliterator<MergedAnnotation<A>> spliterator( |
||||
@Nullable Object annotationType) { |
||||
return new AnnotationsSpliterator<>(annotationType); |
||||
} |
||||
|
||||
@Override |
||||
public <A extends Annotation> boolean isPresent(Class<A> annotationType) { |
||||
return isPresent(annotationType, false); |
||||
} |
||||
|
||||
@Override |
||||
public boolean isPresent(String annotationType) { |
||||
return isPresent(annotationType, false); |
||||
} |
||||
|
||||
@Override |
||||
public <A extends Annotation> boolean isDirectlyPresent(Class<A> annotationType) { |
||||
return isPresent(annotationType, true); |
||||
} |
||||
|
||||
@Override |
||||
public boolean isDirectlyPresent(String annotationType) { |
||||
return isPresent(annotationType, true); |
||||
} |
||||
|
||||
private boolean isPresent(Object requiredType, boolean directOnly) { |
||||
for (MergedAnnotation<?> annotation : this.annotations) { |
||||
Class<? extends Annotation> type = annotation.getType(); |
||||
if (type == requiredType || type.getName().equals(requiredType)) { |
||||
return true; |
||||
} |
||||
} |
||||
if (!directOnly) { |
||||
for (AnnotationTypeMappings mappings : this.mappings) { |
||||
for (int i = 1; i < mappings.size(); i++) { |
||||
AnnotationTypeMapping mapping = mappings.get(i); |
||||
if (isMappingForType(mapping, requiredType)) { |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public <A extends Annotation> MergedAnnotation<A> get(Class<A> annotationType) { |
||||
return get(annotationType, null, null); |
||||
} |
||||
|
||||
@Override |
||||
public <A extends Annotation> MergedAnnotation<A> get(Class<A> annotationType, |
||||
@Nullable Predicate<? super MergedAnnotation<A>> predicate) { |
||||
|
||||
return get(annotationType, predicate, null); |
||||
} |
||||
|
||||
@Override |
||||
public <A extends Annotation> MergedAnnotation<A> get(Class<A> annotationType, |
||||
@Nullable Predicate<? super MergedAnnotation<A>> predicate, |
||||
@Nullable MergedAnnotationSelector<A> selector) { |
||||
MergedAnnotation<A> result = find(annotationType, predicate, selector); |
||||
return (result != null ? result : MergedAnnotation.missing()); |
||||
} |
||||
|
||||
@Override |
||||
public <A extends Annotation> MergedAnnotation<A> get(String annotationType) { |
||||
return get(annotationType, null, null); |
||||
} |
||||
|
||||
@Override |
||||
public <A extends Annotation> MergedAnnotation<A> get(String annotationType, |
||||
@Nullable Predicate<? super MergedAnnotation<A>> predicate) { |
||||
|
||||
return get(annotationType, predicate, null); |
||||
} |
||||
|
||||
@Override |
||||
public <A extends Annotation> MergedAnnotation<A> get(String annotationType, |
||||
@Nullable Predicate<? super MergedAnnotation<A>> predicate, |
||||
@Nullable MergedAnnotationSelector<A> selector) { |
||||
|
||||
MergedAnnotation<A> result = find(annotationType, predicate, selector); |
||||
return (result != null ? result : MergedAnnotation.missing()); |
||||
} |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
private <A extends Annotation> MergedAnnotation<A> find(Object requiredType, |
||||
Predicate<? super MergedAnnotation<A>> predicate, |
||||
MergedAnnotationSelector<A> selector) { |
||||
if (selector == null) { |
||||
selector = MergedAnnotationSelectors.nearest(); |
||||
} |
||||
MergedAnnotation<A> result = null; |
||||
for (int i = 0; i < this.annotations.length; i++) { |
||||
MergedAnnotation<?> root = this.annotations[i]; |
||||
AnnotationTypeMappings mappings = this.mappings[i]; |
||||
for (int mappingIndex = 0; mappingIndex < mappings.size(); mappingIndex++) { |
||||
AnnotationTypeMapping mapping = mappings.get(mappingIndex); |
||||
if (!isMappingForType(mapping, requiredType)) { |
||||
continue; |
||||
} |
||||
MergedAnnotation<A> candidate = (mappingIndex == 0 |
||||
? (MergedAnnotation<A>) root |
||||
: TypeMappedAnnotation.createIfPossible(mapping, root, IntrospectionFailureLogger.INFO)); |
||||
if (candidate != null && (predicate == null || predicate.test(candidate))) { |
||||
if (selector.isBestCandidate(candidate)) { |
||||
return candidate; |
||||
} |
||||
result = (result != null ? selector.select(result, candidate) : candidate); |
||||
} |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
@Override |
||||
public <A extends Annotation> Stream<MergedAnnotation<A>> stream(Class<A> annotationType) { |
||||
return StreamSupport.stream(spliterator(annotationType), false); |
||||
} |
||||
|
||||
@Override |
||||
public <A extends Annotation> Stream<MergedAnnotation<A>> stream(String annotationType) { |
||||
return StreamSupport.stream(spliterator(annotationType), false); |
||||
} |
||||
|
||||
@Override |
||||
public Stream<MergedAnnotation<Annotation>> stream() { |
||||
return StreamSupport.stream(spliterator(), false); |
||||
} |
||||
|
||||
private static boolean isMappingForType(AnnotationTypeMapping mapping, @Nullable Object requiredType) { |
||||
if (requiredType == null) { |
||||
return true; |
||||
} |
||||
Class<? extends Annotation> actualType = mapping.getAnnotationType(); |
||||
return (actualType == requiredType || actualType.getName().equals(requiredType)); |
||||
} |
||||
|
||||
static MergedAnnotations of(Collection<MergedAnnotation<?>> annotations) { |
||||
Assert.notNull(annotations, "Annotations must not be null"); |
||||
if(annotations.isEmpty()) { |
||||
return TypeMappedAnnotations.NONE; |
||||
} |
||||
return new MergedAnnotationsCollection(annotations); |
||||
} |
||||
|
||||
|
||||
private class AnnotationsSpliterator<A extends Annotation> implements Spliterator<MergedAnnotation<A>> { |
||||
|
||||
@Nullable |
||||
private Object requiredType; |
||||
|
||||
private final int[] mappingCursors; |
||||
|
||||
public AnnotationsSpliterator(@Nullable Object requiredType) { |
||||
this.mappingCursors = new int[annotations.length]; |
||||
this.requiredType = requiredType; |
||||
} |
||||
|
||||
@Override |
||||
public boolean tryAdvance(Consumer<? super MergedAnnotation<A>> action) { |
||||
int lowestDepth = Integer.MAX_VALUE; |
||||
int annotationResult = -1; |
||||
for (int annotationIndex = 0; annotationIndex < annotations.length; annotationIndex++) { |
||||
AnnotationTypeMapping mapping = getNextSuitableMapping(annotationIndex); |
||||
if (mapping != null && mapping.getDepth() < lowestDepth) { |
||||
annotationResult = annotationIndex; |
||||
lowestDepth = mapping.getDepth(); |
||||
} |
||||
if (lowestDepth == 0) { |
||||
break; |
||||
} |
||||
} |
||||
if (annotationResult != -1) { |
||||
MergedAnnotation<A> mergedAnnotation = createMergedAnnotationIfPossible(annotationResult, this.mappingCursors[annotationResult]); |
||||
this.mappingCursors[annotationResult]++; |
||||
if (mergedAnnotation == null) { |
||||
return tryAdvance(action); |
||||
} |
||||
action.accept(mergedAnnotation); |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
@Nullable |
||||
private AnnotationTypeMapping getNextSuitableMapping(int annotationIndex) { |
||||
AnnotationTypeMapping mapping; |
||||
do { |
||||
mapping = getMapping(annotationIndex, this.mappingCursors[annotationIndex]); |
||||
if (mapping != null && isMappingForType(mapping, this.requiredType)) { |
||||
return mapping; |
||||
} |
||||
this.mappingCursors[annotationIndex]++; |
||||
} |
||||
while (mapping != null); |
||||
return null; |
||||
} |
||||
|
||||
@Nullable |
||||
private AnnotationTypeMapping getMapping(int annotationIndex, int mappingIndex) { |
||||
AnnotationTypeMappings mappings = MergedAnnotationsCollection.this.mappings[annotationIndex]; |
||||
return (mappingIndex < mappings.size() ? mappings.get(mappingIndex) : null); |
||||
} |
||||
|
||||
@Nullable |
||||
@SuppressWarnings("unchecked") |
||||
private MergedAnnotation<A> createMergedAnnotationIfPossible( |
||||
int annotationIndex, int mappingIndex) { |
||||
MergedAnnotation<?> root = annotations[annotationIndex]; |
||||
if(mappingIndex == 0) { |
||||
return (MergedAnnotation<A>) root; |
||||
} |
||||
IntrospectionFailureLogger logger = (this.requiredType != null |
||||
? IntrospectionFailureLogger.INFO |
||||
: IntrospectionFailureLogger.DEBUG); |
||||
return TypeMappedAnnotation.createIfPossible( |
||||
mappings[annotationIndex].get(mappingIndex), root, logger); |
||||
} |
||||
|
||||
@Override |
||||
public Spliterator<MergedAnnotation<A>> trySplit() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public long estimateSize() { |
||||
int size = 0; |
||||
for (int i = 0; i < annotations.length; i++) { |
||||
AnnotationTypeMappings mappings = MergedAnnotationsCollection.this.mappings[i]; |
||||
int numberOfMappings = mappings.size(); |
||||
numberOfMappings -= Math.min(this.mappingCursors[i], mappings.size()); |
||||
size += numberOfMappings; |
||||
} |
||||
return size; |
||||
} |
||||
|
||||
@Override |
||||
public int characteristics() { |
||||
return NONNULL | IMMUTABLE; |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
@ -0,0 +1,312 @@
@@ -0,0 +1,312 @@
|
||||
/* |
||||
* Copyright 2002-2019 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.annotation; |
||||
|
||||
import java.lang.annotation.Annotation; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.util.ArrayList; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
import java.util.Spliterator; |
||||
|
||||
import org.junit.Test; |
||||
|
||||
import static org.assertj.core.api.Assertions.*; |
||||
import static org.mockito.BDDMockito.*; |
||||
|
||||
/** |
||||
* Tests for {@link MergedAnnotationsCollection}. |
||||
* |
||||
* @author Phillip Webb |
||||
*/ |
||||
public class MergedAnnotationsCollectionTests { |
||||
|
||||
@Test |
||||
public void ofWhenDirectAnnotationsIsNullThrowsException() { |
||||
assertThatIllegalArgumentException().isThrownBy( |
||||
() -> MergedAnnotationsCollection.of(null)).withMessage( |
||||
"Annotations must not be null"); |
||||
} |
||||
|
||||
@Test |
||||
public void ofWhenEmptyReturnsSharedNoneInstance() { |
||||
MergedAnnotations annotations = MergedAnnotationsCollection.of(new ArrayList<>()); |
||||
assertThat(annotations).isSameAs(TypeMappedAnnotations.NONE); |
||||
} |
||||
|
||||
@Test |
||||
public void createWhenAnnotationIsNotDirectlyPresentThrowsException() { |
||||
MergedAnnotation<?> annotation = mock(MergedAnnotation.class); |
||||
given(annotation.isDirectlyPresent()).willReturn(false); |
||||
assertThatIllegalArgumentException().isThrownBy(() -> { |
||||
MergedAnnotationsCollection.of(Collections.singleton(annotation)); |
||||
}).withMessage("Annotation must be directly present"); |
||||
} |
||||
|
||||
@Test |
||||
public void createWhenAnnotationAggregateIndexIsNotZeroThrowsException() { |
||||
MergedAnnotation<?> annotation = mock(MergedAnnotation.class); |
||||
given(annotation.isDirectlyPresent()).willReturn(true); |
||||
given(annotation.getAggregateIndex()).willReturn(1); |
||||
assertThatIllegalArgumentException().isThrownBy(() -> { |
||||
MergedAnnotationsCollection.of(Collections.singleton(annotation)); |
||||
}).withMessage("Annotation must have aggregate index of zero"); |
||||
} |
||||
|
||||
@Test |
||||
public void interateIteratesInCorrectOrder() { |
||||
MergedAnnotations annotations = getDirectAndSimple(); |
||||
List<Class<?>> types = new ArrayList<>(); |
||||
for (MergedAnnotation<?> annotation : annotations) { |
||||
types.add(annotation.getType()); |
||||
} |
||||
assertThat(types).containsExactly(Direct.class, Simple.class, Meta1.class, |
||||
Meta2.class, Meta11.class); |
||||
} |
||||
|
||||
@Test |
||||
public void spliteratorIteratesInCorrectOrder() { |
||||
MergedAnnotations annotations = getDirectAndSimple(); |
||||
Spliterator<MergedAnnotation<Annotation>> spliterator = annotations.spliterator(); |
||||
List<Class<?>> types = new ArrayList<>(); |
||||
spliterator.forEachRemaining(annotation -> types.add(annotation.getType())); |
||||
assertThat(types).containsExactly(Direct.class, Simple.class, Meta1.class, |
||||
Meta2.class, Meta11.class); |
||||
} |
||||
|
||||
@Test |
||||
public void spliteratorEstimatesSize() { |
||||
MergedAnnotations annotations = getDirectAndSimple(); |
||||
Spliterator<MergedAnnotation<Annotation>> spliterator = annotations.spliterator(); |
||||
assertThat(spliterator.estimateSize()).isEqualTo(5); |
||||
spliterator.tryAdvance( |
||||
annotation -> assertThat(annotation.getType()).isEqualTo(Direct.class)); |
||||
assertThat(spliterator.estimateSize()).isEqualTo(4); |
||||
} |
||||
|
||||
@Test |
||||
public void isPresentWhenDirectlyPresentReturnsTrue() { |
||||
MergedAnnotations annotations = getDirectAndSimple(); |
||||
assertThat(annotations.isPresent(Direct.class)).isTrue(); |
||||
assertThat(annotations.isPresent(Direct.class.getName())).isTrue(); |
||||
} |
||||
|
||||
@Test |
||||
public void isPresentWhenMetaPresentReturnsTrue() { |
||||
MergedAnnotations annotations = getDirectAndSimple(); |
||||
assertThat(annotations.isPresent(Meta11.class)).isTrue(); |
||||
assertThat(annotations.isPresent(Meta11.class.getName())).isTrue(); |
||||
} |
||||
|
||||
@Test |
||||
public void isPresentWhenNotPresentReturnsFalse() { |
||||
MergedAnnotations annotations = getDirectAndSimple(); |
||||
assertThat(annotations.isPresent(Missing.class)).isFalse(); |
||||
assertThat(annotations.isPresent(Missing.class.getName())).isFalse(); |
||||
|
||||
} |
||||
|
||||
@Test |
||||
public void isDirectlyPresentWhenDirectlyPresentReturnsTrue() { |
||||
MergedAnnotations annotations = getDirectAndSimple(); |
||||
assertThat(annotations.isDirectlyPresent(Direct.class)).isTrue(); |
||||
assertThat(annotations.isDirectlyPresent(Direct.class.getName())).isTrue(); |
||||
} |
||||
|
||||
@Test |
||||
public void isDirectlyPresentWhenMetaPresentReturnsFalse() { |
||||
MergedAnnotations annotations = getDirectAndSimple(); |
||||
assertThat(annotations.isDirectlyPresent(Meta11.class)).isFalse(); |
||||
assertThat(annotations.isDirectlyPresent(Meta11.class.getName())).isFalse(); |
||||
} |
||||
|
||||
@Test |
||||
public void isDirectlyPresentWhenNotPresentReturnsFalse() { |
||||
MergedAnnotations annotations = getDirectAndSimple(); |
||||
assertThat(annotations.isDirectlyPresent(Missing.class)).isFalse(); |
||||
assertThat(annotations.isDirectlyPresent(Missing.class.getName())).isFalse(); |
||||
} |
||||
|
||||
@Test |
||||
public void getReturnsAppropriateAnnotation() { |
||||
MergedAnnotations annotations = getMutiRoute1(); |
||||
assertThat(annotations.get(MutiRouteTarget.class).getString( |
||||
MergedAnnotation.VALUE)).isEqualTo("12"); |
||||
assertThat(annotations.get(MutiRouteTarget.class.getName()).getString( |
||||
MergedAnnotation.VALUE)).isEqualTo("12"); |
||||
} |
||||
|
||||
@Test |
||||
public void getWhenNotPresentReturnsMissing() { |
||||
MergedAnnotations annotations = getDirectAndSimple(); |
||||
assertThat(annotations.get(Missing.class)).isEqualTo(MergedAnnotation.missing()); |
||||
} |
||||
|
||||
@Test |
||||
public void getWithPredicateReturnsOnlyMatching() { |
||||
MergedAnnotations annotations = getMutiRoute1(); |
||||
assertThat(annotations.get(MutiRouteTarget.class, |
||||
annotation -> annotation.getDepth() >= 3).getString( |
||||
MergedAnnotation.VALUE)).isEqualTo("111"); |
||||
} |
||||
|
||||
@Test |
||||
public void getWithSelectorReturnsSelected() { |
||||
MergedAnnotations annotations = getMutiRoute1(); |
||||
MergedAnnotationSelector<MutiRouteTarget> deepest = (existing, |
||||
candidate) -> candidate.getDepth() > existing.getDepth() ? candidate |
||||
: existing; |
||||
assertThat(annotations.get(MutiRouteTarget.class, null, deepest).getString( |
||||
MergedAnnotation.VALUE)).isEqualTo("111"); |
||||
} |
||||
|
||||
@Test |
||||
public void streamStreamsInCorrectOrder() { |
||||
MergedAnnotations annotations = getDirectAndSimple(); |
||||
List<Class<?>> types = new ArrayList<>(); |
||||
annotations.stream().forEach(annotation -> types.add(annotation.getType())); |
||||
assertThat(types).containsExactly(Direct.class, Simple.class, Meta1.class, |
||||
Meta2.class, Meta11.class); |
||||
} |
||||
|
||||
@Test |
||||
public void streamWithTypeStreamsInCorrectOrder() { |
||||
MergedAnnotations annotations = getMutiRoute1(); |
||||
List<String> values = new ArrayList<>(); |
||||
annotations.stream(MutiRouteTarget.class).forEach( |
||||
annotation -> values.add(annotation.getString(MergedAnnotation.VALUE))); |
||||
assertThat(values).containsExactly("12", "111"); |
||||
} |
||||
|
||||
@Test |
||||
public void getMetaWhenRootHasAttributeValuesShouldAlaisAttributes() { |
||||
MergedAnnotation<Alaised> root = MergedAnnotation.of(null, null, Alaised.class, |
||||
Collections.singletonMap("testAlias", "test")); |
||||
MergedAnnotations annotations = MergedAnnotationsCollection.of( |
||||
Collections.singleton(root)); |
||||
MergedAnnotation<AlaisTarget> metaAnnotation = annotations.get(AlaisTarget.class); |
||||
assertThat(metaAnnotation.getString("test")).isEqualTo("test"); |
||||
} |
||||
|
||||
@Test |
||||
public void getMetaWhenRootHasNoAttributeValuesShouldAlaisAttributes() { |
||||
MergedAnnotation<Alaised> root = MergedAnnotation.of(null, null, Alaised.class, |
||||
Collections.emptyMap()); |
||||
MergedAnnotations annotations = MergedAnnotationsCollection.of( |
||||
Collections.singleton(root)); |
||||
MergedAnnotation<AlaisTarget> metaAnnotation = annotations.get(AlaisTarget.class); |
||||
assertThat(root.getString("testAlias")).isEqualTo("newdefault"); |
||||
assertThat(metaAnnotation.getString("test")).isEqualTo("newdefault"); |
||||
} |
||||
|
||||
private MergedAnnotations getDirectAndSimple() { |
||||
List<MergedAnnotation<?>> list = new ArrayList<>(); |
||||
list.add(MergedAnnotation.of(null, null, Direct.class, Collections.emptyMap())); |
||||
list.add(MergedAnnotation.of(null, null, Simple.class, Collections.emptyMap())); |
||||
return MergedAnnotationsCollection.of(list); |
||||
} |
||||
|
||||
private MergedAnnotations getMutiRoute1() { |
||||
List<MergedAnnotation<?>> list = new ArrayList<>(); |
||||
list.add(MergedAnnotation.of(null, null, MutiRoute1.class, |
||||
Collections.emptyMap())); |
||||
return MergedAnnotationsCollection.of(list); |
||||
} |
||||
|
||||
@Meta1 |
||||
@Meta2 |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@interface Direct { |
||||
|
||||
} |
||||
|
||||
@Meta11 |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@interface Meta1 { |
||||
|
||||
} |
||||
|
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@interface Meta2 { |
||||
|
||||
} |
||||
|
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@interface Meta11 { |
||||
|
||||
} |
||||
|
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@interface Simple { |
||||
|
||||
} |
||||
|
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@interface Missing { |
||||
|
||||
} |
||||
|
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@interface MutiRouteTarget { |
||||
|
||||
String value(); |
||||
|
||||
} |
||||
|
||||
@MutiRoute11 |
||||
@MutiRoute12 |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@interface MutiRoute1 { |
||||
|
||||
} |
||||
|
||||
@MutiRoute111 |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@interface MutiRoute11 { |
||||
|
||||
} |
||||
|
||||
@MutiRouteTarget("12") |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@interface MutiRoute12 { |
||||
|
||||
} |
||||
|
||||
@MutiRouteTarget("111") |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@interface MutiRoute111 { |
||||
|
||||
} |
||||
|
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@interface AlaisTarget { |
||||
|
||||
String test() default "default"; |
||||
|
||||
} |
||||
|
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@AlaisTarget |
||||
@interface Alaised { |
||||
|
||||
@AliasFor(annotation = AlaisTarget.class, attribute = "test") |
||||
String testAlias() default "newdefault"; |
||||
|
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue