AnnotationMetadataTests.java 24.8 KB
Newer Older
A
Arjen Poutsma 已提交
1
/*
J
Juergen Hoeller 已提交
2
 * Copyright 2002-2019 the original author or authors.
A
Arjen Poutsma 已提交
3 4 5 6 7
 *
 * 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
 *
S
Spring Operator 已提交
8
 *      https://www.apache.org/licenses/LICENSE-2.0
A
Arjen Poutsma 已提交
9 10 11 12 13 14 15 16 17 18 19
 *
 * 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.type;

import java.io.Serializable;
20
import java.lang.annotation.Annotation;
21
import java.lang.annotation.Documented;
22
import java.lang.annotation.ElementType;
23
import java.lang.annotation.Inherited;
24 25 26
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
27 28 29
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
30
import java.util.Set;
A
Arjen Poutsma 已提交
31

32
import org.junit.jupiter.api.Test;
33

34
import org.springframework.core.annotation.AliasFor;
35
import org.springframework.core.annotation.AnnotationAttributes;
A
Arjen Poutsma 已提交
36
import org.springframework.core.type.classreading.MetadataReader;
37
import org.springframework.core.type.classreading.MetadataReaderFactory;
A
Arjen Poutsma 已提交
38 39 40
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import org.springframework.stereotype.Component;

41
import static org.assertj.core.api.Assertions.assertThat;
42

A
Arjen Poutsma 已提交
43
/**
44 45 46
 * Unit tests demonstrating that the reflection-based {@link StandardAnnotationMetadata}
 * and ASM-based {@code AnnotationMetadataReadingVisitor} produce identical output.
 *
A
Arjen Poutsma 已提交
47
 * @author Juergen Hoeller
48
 * @author Chris Beams
49
 * @author Phillip Webb
50
 * @author Sam Brannen
A
Arjen Poutsma 已提交
51
 */
52
class AnnotationMetadataTests {
A
Arjen Poutsma 已提交
53

54
	@Test
55
	void standardAnnotationMetadata() {
56
		AnnotationMetadata metadata = AnnotationMetadata.introspect(AnnotatedComponent.class);
57 58
		doTestAnnotationInfo(metadata);
		doTestMethodAnnotationInfo(metadata);
A
Arjen Poutsma 已提交
59 60
	}

61
	@Test
62
	void asmAnnotationMetadata() throws Exception {
A
Arjen Poutsma 已提交
63 64
		MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
		MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(AnnotatedComponent.class.getName());
65 66 67 68 69
		AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
		doTestAnnotationInfo(metadata);
		doTestMethodAnnotationInfo(metadata);
	}

70
	@Test
71
	void standardAnnotationMetadataForSubclass() {
72
		AnnotationMetadata metadata = AnnotationMetadata.introspect(AnnotatedComponentSubClass.class);
73 74 75 76
		doTestSubClassAnnotationInfo(metadata);
	}

	@Test
77
	void asmAnnotationMetadataForSubclass() throws Exception {
78 79 80 81 82 83
		MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
		MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(AnnotatedComponentSubClass.class.getName());
		AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
		doTestSubClassAnnotationInfo(metadata);
	}

84
	private void doTestSubClassAnnotationInfo(AnnotationMetadata metadata) {
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
		assertThat(metadata.getClassName()).isEqualTo(AnnotatedComponentSubClass.class.getName());
		assertThat(metadata.isInterface()).isFalse();
		assertThat(metadata.isAnnotation()).isFalse();
		assertThat(metadata.isAbstract()).isFalse();
		assertThat(metadata.isConcrete()).isTrue();
		assertThat(metadata.hasSuperClass()).isTrue();
		assertThat(metadata.getSuperClassName()).isEqualTo(AnnotatedComponent.class.getName());
		assertThat(metadata.getInterfaceNames().length).isEqualTo(0);
		assertThat(metadata.isAnnotated(Component.class.getName())).isFalse();
		assertThat(metadata.isAnnotated(Scope.class.getName())).isFalse();
		assertThat(metadata.isAnnotated(SpecialAttr.class.getName())).isFalse();
		assertThat(metadata.hasAnnotation(Component.class.getName())).isFalse();
		assertThat(metadata.hasAnnotation(Scope.class.getName())).isFalse();
		assertThat(metadata.hasAnnotation(SpecialAttr.class.getName())).isFalse();
		assertThat(metadata.getAnnotationTypes()).hasSize(0);
		assertThat(metadata.getAnnotationAttributes(Component.class.getName())).isNull();
		assertThat(metadata.getAnnotatedMethods(DirectAnnotation.class.getName()).size()).isEqualTo(0);
		assertThat(metadata.isAnnotated(IsAnnotatedAnnotation.class.getName())).isEqualTo(false);
		assertThat(metadata.getAllAnnotationAttributes(DirectAnnotation.class.getName())).isNull();
104 105 106
	}

	@Test
107
	void standardAnnotationMetadataForInterface() {
108
		AnnotationMetadata metadata = AnnotationMetadata.introspect(AnnotationMetadata.class);
109 110 111 112
		doTestMetadataForInterfaceClass(metadata);
	}

	@Test
113
	void asmAnnotationMetadataForInterface() throws Exception {
114 115 116 117 118 119 120
		MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
		MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(AnnotationMetadata.class.getName());
		AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
		doTestMetadataForInterfaceClass(metadata);
	}

	private void doTestMetadataForInterfaceClass(AnnotationMetadata metadata) {
121 122 123 124 125 126 127 128 129 130 131
		assertThat(metadata.getClassName()).isEqualTo(AnnotationMetadata.class.getName());
		assertThat(metadata.isInterface()).isTrue();
		assertThat(metadata.isAnnotation()).isFalse();
		assertThat(metadata.isAbstract()).isTrue();
		assertThat(metadata.isConcrete()).isFalse();
		assertThat(metadata.hasSuperClass()).isFalse();
		assertThat(metadata.getSuperClassName()).isNull();
		assertThat(metadata.getInterfaceNames().length).isEqualTo(2);
		assertThat(metadata.getInterfaceNames()[0]).isEqualTo(ClassMetadata.class.getName());
		assertThat(metadata.getInterfaceNames()[1]).isEqualTo(AnnotatedTypeMetadata.class.getName());
		assertThat(metadata.getAnnotationTypes()).hasSize(0);
132 133 134
	}

	@Test
135
	void standardAnnotationMetadataForAnnotation() {
136
		AnnotationMetadata metadata = AnnotationMetadata.introspect(Component.class);
137 138 139 140
		doTestMetadataForAnnotationClass(metadata);
	}

	@Test
141
	void asmAnnotationMetadataForAnnotation() throws Exception {
142 143 144 145 146 147 148
		MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
		MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(Component.class.getName());
		AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
		doTestMetadataForAnnotationClass(metadata);
	}

	private void doTestMetadataForAnnotationClass(AnnotationMetadata metadata) {
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
		assertThat(metadata.getClassName()).isEqualTo(Component.class.getName());
		assertThat(metadata.isInterface()).isTrue();
		assertThat(metadata.isAnnotation()).isTrue();
		assertThat(metadata.isAbstract()).isTrue();
		assertThat(metadata.isConcrete()).isFalse();
		assertThat(metadata.hasSuperClass()).isFalse();
		assertThat(metadata.getSuperClassName()).isNull();
		assertThat(metadata.getInterfaceNames().length).isEqualTo(1);
		assertThat(metadata.getInterfaceNames()[0]).isEqualTo(Annotation.class.getName());
		assertThat(metadata.isAnnotated(Documented.class.getName())).isFalse();
		assertThat(metadata.isAnnotated(Scope.class.getName())).isFalse();
		assertThat(metadata.isAnnotated(SpecialAttr.class.getName())).isFalse();
		assertThat(metadata.hasAnnotation(Documented.class.getName())).isFalse();
		assertThat(metadata.hasAnnotation(Scope.class.getName())).isFalse();
		assertThat(metadata.hasAnnotation(SpecialAttr.class.getName())).isFalse();
		assertThat(metadata.getAnnotationTypes()).hasSize(1);
165 166
	}

167 168 169 170 171 172 173 174
	/**
	 * In order to preserve backward-compatibility, {@link StandardAnnotationMetadata}
	 * defaults to return nested annotations and annotation arrays as actual
	 * Annotation instances. It is recommended for compatibility with ASM-based
	 * AnnotationMetadata implementations to set the 'nestedAnnotationsAsMap' flag to
	 * 'true' as is done in the main test above.
	 */
	@Test
175
	@Deprecated
176
	void standardAnnotationMetadata_nestedAnnotationsAsMap_false() {
177 178
		AnnotationMetadata metadata = new StandardAnnotationMetadata(AnnotatedComponent.class);
		AnnotationAttributes specialAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes(SpecialAttr.class.getName());
179
		Annotation[] nestedAnnoArray = (Annotation[]) specialAttrs.get("nestedAnnoArray");
180
		assertThat(nestedAnnoArray[0]).isInstanceOf(NestedAnno.class);
A
Arjen Poutsma 已提交
181 182
	}

183
	@Test
184
	@Deprecated
185
	void metaAnnotationOverridesUsingStandardAnnotationMetadata() {
186
		AnnotationMetadata metadata = new StandardAnnotationMetadata(ComposedConfigurationWithAttributeOverridesClass.class);
187 188 189 190
		assertMetaAnnotationOverrides(metadata);
	}

	@Test
191
	void metaAnnotationOverridesUsingAnnotationMetadataReadingVisitor() throws Exception {
192 193 194 195 196 197 198 199
		MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
		MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(ComposedConfigurationWithAttributeOverridesClass.class.getName());
		AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
		assertMetaAnnotationOverrides(metadata);
	}

	private void assertMetaAnnotationOverrides(AnnotationMetadata metadata) {
		AnnotationAttributes attributes = (AnnotationAttributes) metadata.getAnnotationAttributes(
J
Juergen Hoeller 已提交
200
				TestComponentScan.class.getName(), false);
201 202 203
		assertThat(attributes.getStringArray("basePackages")).containsExactly("org.example.componentscan");
		assertThat(attributes.getStringArray("value")).isEmpty();
		assertThat(attributes.getClassArray("basePackageClasses")).isEmpty();
204 205
	}

J
Juergen Hoeller 已提交
206
	@Test  // SPR-11649
207
	void multipleAnnotationsWithIdenticalAttributeNamesUsingStandardAnnotationMetadata() {
208
		AnnotationMetadata metadata = AnnotationMetadata.introspect(NamedAnnotationsClass.class);
209 210
		assertMultipleAnnotationsWithIdenticalAttributeNames(metadata);
	}
211

J
Juergen Hoeller 已提交
212
	@Test  // SPR-11649
213
	void multipleAnnotationsWithIdenticalAttributeNamesUsingAnnotationMetadataReadingVisitor() throws Exception {
214 215 216 217 218
		MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
		MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(NamedAnnotationsClass.class.getName());
		AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
		assertMultipleAnnotationsWithIdenticalAttributeNames(metadata);
	}
219

J
Juergen Hoeller 已提交
220
	@Test  // SPR-11649
221
	void composedAnnotationWithMetaAnnotationsWithIdenticalAttributeNamesUsingStandardAnnotationMetadata() {
222
		AnnotationMetadata metadata = AnnotationMetadata.introspect(NamedComposedAnnotationClass.class);
223 224
		assertMultipleAnnotationsWithIdenticalAttributeNames(metadata);
	}
225

J
Juergen Hoeller 已提交
226
	@Test  // SPR-11649
227
	void composedAnnotationWithMetaAnnotationsWithIdenticalAttributeNamesUsingAnnotationMetadataReadingVisitor() throws Exception {
228 229 230 231 232 233
		MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
		MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(NamedComposedAnnotationClass.class.getName());
		AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
		assertMultipleAnnotationsWithIdenticalAttributeNames(metadata);
	}

234
	@Test
235
	void inheritedAnnotationWithMetaAnnotationsWithIdenticalAttributeNamesUsingStandardAnnotationMetadata() {
236
		AnnotationMetadata metadata = AnnotationMetadata.introspect(NamedComposedAnnotationExtended.class);
237
		assertThat(metadata.hasAnnotation(NamedComposedAnnotation.class.getName())).isFalse();
238 239 240
	}

	@Test
241
	void inheritedAnnotationWithMetaAnnotationsWithIdenticalAttributeNamesUsingAnnotationMetadataReadingVisitor() throws Exception {
242 243 244
		MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
		MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(NamedComposedAnnotationExtended.class.getName());
		AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
245
		assertThat(metadata.hasAnnotation(NamedComposedAnnotation.class.getName())).isFalse();
246 247
	}

248

249 250 251 252
	private void assertMultipleAnnotationsWithIdenticalAttributeNames(AnnotationMetadata metadata) {
		AnnotationAttributes attributes1 = (AnnotationAttributes) metadata.getAnnotationAttributes(
				NamedAnnotation1.class.getName(), false);
		String name1 = attributes1.getString("name");
253
		assertThat(name1).as("name of NamedAnnotation1").isEqualTo("name 1");
254 255 256 257

		AnnotationAttributes attributes2 = (AnnotationAttributes) metadata.getAnnotationAttributes(
				NamedAnnotation2.class.getName(), false);
		String name2 = attributes2.getString("name");
258
		assertThat(name2).as("name of NamedAnnotation2").isEqualTo("name 2");
259 260 261 262

		AnnotationAttributes attributes3 = (AnnotationAttributes) metadata.getAnnotationAttributes(
				NamedAnnotation3.class.getName(), false);
		String name3 = attributes3.getString("name");
263
		assertThat(name3).as("name of NamedAnnotation3").isEqualTo("name 3");
264 265
	}

A
Arjen Poutsma 已提交
266
	private void doTestAnnotationInfo(AnnotationMetadata metadata) {
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
		assertThat(metadata.getClassName()).isEqualTo(AnnotatedComponent.class.getName());
		assertThat(metadata.isInterface()).isFalse();
		assertThat(metadata.isAnnotation()).isFalse();
		assertThat(metadata.isAbstract()).isFalse();
		assertThat(metadata.isConcrete()).isTrue();
		assertThat(metadata.hasSuperClass()).isTrue();
		assertThat(metadata.getSuperClassName()).isEqualTo(Object.class.getName());
		assertThat(metadata.getInterfaceNames().length).isEqualTo(1);
		assertThat(metadata.getInterfaceNames()[0]).isEqualTo(Serializable.class.getName());

		assertThat(metadata.hasAnnotation(Component.class.getName())).isTrue();
		assertThat(metadata.hasAnnotation(Scope.class.getName())).isTrue();
		assertThat(metadata.hasAnnotation(SpecialAttr.class.getName())).isTrue();
		assertThat(metadata.getAnnotationTypes()).hasSize(6);
		assertThat(metadata.getAnnotationTypes().contains(Component.class.getName())).isTrue();
		assertThat(metadata.getAnnotationTypes().contains(Scope.class.getName())).isTrue();
		assertThat(metadata.getAnnotationTypes().contains(SpecialAttr.class.getName())).isTrue();
284 285

		AnnotationAttributes compAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes(Component.class.getName());
286 287
		assertThat(compAttrs).hasSize(1);
		assertThat(compAttrs.getString("value")).isEqualTo("myName");
288
		AnnotationAttributes scopeAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes(Scope.class.getName());
289 290
		assertThat(scopeAttrs).hasSize(1);
		assertThat(scopeAttrs.getString("value")).isEqualTo("myScope");
291 292 293

		Set<MethodMetadata> methods = metadata.getAnnotatedMethods(DirectAnnotation.class.getName());
		MethodMetadata method = methods.iterator().next();
294 295
		assertThat(method.getAnnotationAttributes(DirectAnnotation.class.getName()).get("value")).isEqualTo("direct");
		assertThat(method.getAnnotationAttributes(DirectAnnotation.class.getName()).get("myValue")).isEqualTo("direct");
296
		List<Object> allMeta = method.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("value");
297
		assertThat(new HashSet<>(allMeta)).isEqualTo(new HashSet<Object>(Arrays.asList("direct", "meta")));
298
		allMeta = method.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("additional");
299
		assertThat(new HashSet<>(allMeta)).isEqualTo(new HashSet<Object>(Arrays.asList("direct")));
300

301
		assertThat(metadata.isAnnotated(IsAnnotatedAnnotation.class.getName())).isTrue();
302

303 304
		{ // perform tests with classValuesAsString = false (the default)
			AnnotationAttributes specialAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes(SpecialAttr.class.getName());
305
			assertThat(specialAttrs).hasSize(6);
306 307
			assertThat(String.class.isAssignableFrom(specialAttrs.getClass("clazz"))).isTrue();
			assertThat(specialAttrs.getEnum("state").equals(Thread.State.NEW)).isTrue();
308 309

			AnnotationAttributes nestedAnno = specialAttrs.getAnnotation("nestedAnno");
310
			assertThat("na").isEqualTo(nestedAnno.getString("value"));
311 312
			assertThat(nestedAnno.getEnum("anEnum").equals(SomeEnum.LABEL1)).isTrue();
			assertThat((Class<?>[]) nestedAnno.get("classArray")).isEqualTo(new Class<?>[] {String.class});
313 314

			AnnotationAttributes[] nestedAnnoArray = specialAttrs.getAnnotationArray("nestedAnnoArray");
315 316
			assertThat(nestedAnnoArray.length).isEqualTo(2);
			assertThat(nestedAnnoArray[0].getString("value")).isEqualTo("default");
317 318
			assertThat(nestedAnnoArray[0].getEnum("anEnum").equals(SomeEnum.DEFAULT)).isTrue();
			assertThat((Class<?>[]) nestedAnnoArray[0].get("classArray")).isEqualTo(new Class<?>[] {Void.class});
319
			assertThat(nestedAnnoArray[1].getString("value")).isEqualTo("na1");
320 321 322
			assertThat(nestedAnnoArray[1].getEnum("anEnum").equals(SomeEnum.LABEL2)).isTrue();
			assertThat((Class<?>[]) nestedAnnoArray[1].get("classArray")).isEqualTo(new Class<?>[] {Number.class});
			assertThat(nestedAnnoArray[1].getClassArray("classArray")).isEqualTo(new Class<?>[] {Number.class});
323 324

			AnnotationAttributes optional = specialAttrs.getAnnotation("optional");
325
			assertThat(optional.getString("value")).isEqualTo("optional");
326 327 328
			assertThat(optional.getEnum("anEnum").equals(SomeEnum.DEFAULT)).isTrue();
			assertThat((Class<?>[]) optional.get("classArray")).isEqualTo(new Class<?>[] {Void.class});
			assertThat(optional.getClassArray("classArray")).isEqualTo(new Class<?>[] {Void.class});
329 330

			AnnotationAttributes[] optionalArray = specialAttrs.getAnnotationArray("optionalArray");
331 332
			assertThat(optionalArray.length).isEqualTo(1);
			assertThat(optionalArray[0].getString("value")).isEqualTo("optional");
333 334 335
			assertThat(optionalArray[0].getEnum("anEnum").equals(SomeEnum.DEFAULT)).isTrue();
			assertThat((Class<?>[]) optionalArray[0].get("classArray")).isEqualTo(new Class<?>[] {Void.class});
			assertThat(optionalArray[0].getClassArray("classArray")).isEqualTo(new Class<?>[] {Void.class});
336

337
			assertThat(metadata.getAnnotationAttributes(DirectAnnotation.class.getName()).get("value")).isEqualTo("direct");
338
			allMeta = metadata.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("value");
339
			assertThat(new HashSet<>(allMeta)).isEqualTo(new HashSet<Object>(Arrays.asList("direct", "meta")));
340
			allMeta = metadata.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("additional");
341
			assertThat(new HashSet<>(allMeta)).isEqualTo(new HashSet<Object>(Arrays.asList("direct", "")));
342 343
			assertThat(metadata.getAnnotationAttributes(DirectAnnotation.class.getName()).get("additional")).isEqualTo("");
			assertThat(((String[]) metadata.getAnnotationAttributes(DirectAnnotation.class.getName()).get("additionalArray")).length).isEqualTo(0);
344 345
		}
		{ // perform tests with classValuesAsString = true
346 347
			AnnotationAttributes specialAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes(
				SpecialAttr.class.getName(), true);
348 349 350
			assertThat(specialAttrs).hasSize(6);
			assertThat(specialAttrs.get("clazz")).isEqualTo(String.class.getName());
			assertThat(specialAttrs.getString("clazz")).isEqualTo(String.class.getName());
351 352

			AnnotationAttributes nestedAnno = specialAttrs.getAnnotation("nestedAnno");
353 354
			assertThat(nestedAnno.getStringArray("classArray")).isEqualTo(new String[] { String.class.getName() });
			assertThat(nestedAnno.getStringArray("classArray")).isEqualTo(new String[] { String.class.getName() });
355 356

			AnnotationAttributes[] nestedAnnoArray = specialAttrs.getAnnotationArray("nestedAnnoArray");
357 358 359 360
			assertThat((String[]) nestedAnnoArray[0].get("classArray")).isEqualTo(new String[] { Void.class.getName() });
			assertThat(nestedAnnoArray[0].getStringArray("classArray")).isEqualTo(new String[] { Void.class.getName() });
			assertThat((String[]) nestedAnnoArray[1].get("classArray")).isEqualTo(new String[] { Number.class.getName() });
			assertThat(nestedAnnoArray[1].getStringArray("classArray")).isEqualTo(new String[] { Number.class.getName() });
361 362

			AnnotationAttributes optional = specialAttrs.getAnnotation("optional");
363 364
			assertThat((String[]) optional.get("classArray")).isEqualTo(new String[] { Void.class.getName() });
			assertThat(optional.getStringArray("classArray")).isEqualTo(new String[] { Void.class.getName() });
365 366

			AnnotationAttributes[] optionalArray = specialAttrs.getAnnotationArray("optionalArray");
367 368
			assertThat((String[]) optionalArray[0].get("classArray")).isEqualTo(new String[] { Void.class.getName() });
			assertThat(optionalArray[0].getStringArray("classArray")).isEqualTo(new String[] { Void.class.getName() });
369

370
			assertThat(metadata.getAnnotationAttributes(DirectAnnotation.class.getName()).get("value")).isEqualTo("direct");
371
			allMeta = metadata.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("value");
372
			assertThat(new HashSet<>(allMeta)).isEqualTo(new HashSet<Object>(Arrays.asList("direct", "meta")));
373
		}
374
	}
J
Juergen Hoeller 已提交
375

376
	private void doTestMethodAnnotationInfo(AnnotationMetadata classMetadata) {
377
		Set<MethodMetadata> methods = classMetadata.getAnnotatedMethods(TestAutowired.class.getName());
378
		assertThat(methods).hasSize(1);
379
		for (MethodMetadata methodMetadata : methods) {
380
			assertThat(methodMetadata.isAnnotated(TestAutowired.class.getName())).isTrue();
381 382
		}
	}
383

384 385 386

	// -------------------------------------------------------------------------

387
	public static enum SomeEnum {
388
		LABEL1, LABEL2, DEFAULT
389 390 391 392 393
	}

	@Target({})
	@Retention(RetentionPolicy.RUNTIME)
	public @interface NestedAnno {
394

395
		String value() default "default";
396

397
		SomeEnum anEnum() default SomeEnum.DEFAULT;
398

399 400
		Class<?>[] classArray() default Void.class;
	}
401 402 403 404 405

	@Target(ElementType.TYPE)
	@Retention(RetentionPolicy.RUNTIME)
	public @interface SpecialAttr {

406
		Class<?> clazz();
A
Arjen Poutsma 已提交
407

408
		Thread.State state();
409 410 411 412 413

		NestedAnno nestedAnno();

		NestedAnno[] nestedAnnoArray();

414
		NestedAnno optional() default @NestedAnno(value = "optional", anEnum = SomeEnum.DEFAULT, classArray = Void.class);
415

416
		NestedAnno[] optionalArray() default { @NestedAnno(value = "optional", anEnum = SomeEnum.DEFAULT, classArray = Void.class) };
A
Arjen Poutsma 已提交
417 418
	}

419
	@Target({ElementType.TYPE, ElementType.METHOD})
420 421
	@Retention(RetentionPolicy.RUNTIME)
	public @interface DirectAnnotation {
422

423 424 425 426 427
		@AliasFor("myValue")
		String value() default "";

		@AliasFor("value")
		String myValue() default "";
428 429

		String additional() default "direct";
430 431

		String[] additionalArray() default "direct";
432 433
	}

434
	@Target(ElementType.TYPE)
435 436 437 438 439 440 441 442 443
	@Retention(RetentionPolicy.RUNTIME)
	public @interface IsAnnotatedAnnotation {
	}

	@Target(ElementType.TYPE)
	@Retention(RetentionPolicy.RUNTIME)
	@DirectAnnotation("meta")
	@IsAnnotatedAnnotation
	public @interface MetaAnnotation {
444 445

		String additional() default "meta";
446 447
	}

448
	@Target({ElementType.TYPE, ElementType.METHOD})
449 450 451 452
	@Retention(RetentionPolicy.RUNTIME)
	@MetaAnnotation
	public @interface MetaMetaAnnotation {
	}
A
Arjen Poutsma 已提交
453

454 455 456
	@Target(ElementType.TYPE)
	@Retention(RetentionPolicy.RUNTIME)
	public @interface EnumSubclasses {
457

458 459 460 461
		SubclassEnum[] value();
	}

	// SPR-10914
462
	public enum SubclassEnum {
463
		FOO {
464
		/* Do not delete! This subclassing is intentional. */
465 466
		},
		BAR {
467
		/* Do not delete! This subclassing is intentional. */
468
		}
469 470
	}

A
Arjen Poutsma 已提交
471 472
	@Component("myName")
	@Scope("myScope")
473 474 475 476
	@SpecialAttr(clazz = String.class, state = Thread.State.NEW,
			nestedAnno = @NestedAnno(value = "na", anEnum = SomeEnum.LABEL1, classArray = {String.class}),
			nestedAnnoArray = {@NestedAnno, @NestedAnno(value = "na1", anEnum = SomeEnum.LABEL2, classArray = {Number.class})})
	@SuppressWarnings({"serial", "unused"})
477
	@DirectAnnotation(value = "direct", additional = "", additionalArray = {})
478
	@MetaMetaAnnotation
479
	@EnumSubclasses({SubclassEnum.FOO, SubclassEnum.BAR})
A
Arjen Poutsma 已提交
480
	private static class AnnotatedComponent implements Serializable {
481

482 483
		@TestAutowired
		public void doWork(@TestQualifier("myColor") java.awt.Color color) {
484
		}
J
Juergen Hoeller 已提交
485

486
		public void doSleep() {
487
		}
488 489 490 491 492

		@DirectAnnotation("direct")
		@MetaMetaAnnotation
		public void meta() {
		}
A
Arjen Poutsma 已提交
493 494
	}

495
	@SuppressWarnings("serial")
496 497 498
	private static class AnnotatedComponentSubClass extends AnnotatedComponent {
	}

499 500 501
	@Target(ElementType.TYPE)
	@Retention(RetentionPolicy.RUNTIME)
	@Component
502
	public @interface TestConfiguration {
503 504 505 506 507 508

		String value() default "";
	}

	@Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.TYPE)
509
	public @interface TestComponentScan {
510 511 512 513 514 515 516 517 518 519 520 521

		String[] value() default {};

		String[] basePackages() default {};

		Class<?>[] basePackageClasses() default {};
	}

	@TestConfiguration
	@TestComponentScan(basePackages = "bogus")
	@Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.TYPE)
522
	public @interface ComposedConfigurationWithAttributeOverrides {
523 524 525 526 527 528 529 530

		String[] basePackages() default {};
	}

	@ComposedConfigurationWithAttributeOverrides(basePackages = "org.example.componentscan")
	public static class ComposedConfigurationWithAttributeOverridesClass {
	}

531 532
	@Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.TYPE)
533
	public @interface NamedAnnotation1 {
534 535 536 537 538
		String name() default "";
	}

	@Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.TYPE)
539
	public @interface NamedAnnotation2 {
540 541 542 543 544
		String name() default "";
	}

	@Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.TYPE)
545
	public @interface NamedAnnotation3 {
546 547 548 549 550 551 552 553 554 555 556 557 558 559
		String name() default "";
	}

	@NamedAnnotation1(name = "name 1")
	@NamedAnnotation2(name = "name 2")
	@NamedAnnotation3(name = "name 3")
	public static class NamedAnnotationsClass {
	}

	@NamedAnnotation1(name = "name 1")
	@NamedAnnotation2(name = "name 2")
	@NamedAnnotation3(name = "name 3")
	@Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.TYPE)
560
	@Inherited
561
	public @interface NamedComposedAnnotation {
562 563 564 565 566 567
	}

	@NamedComposedAnnotation
	public static class NamedComposedAnnotationClass {
	}

568 569 570
	public static class NamedComposedAnnotationExtended extends NamedComposedAnnotationClass {
	}

A
Arjen Poutsma 已提交
571
}