Skip to content

Commit e7ea925

Browse files
committed
Verify that SynthesizedAnnotation must be public
This commit introduces a test that will fail if SynthesizedAnnotation is not public as is required by the contract for getProxyClass() in java.lang.reflect.Proxy. Issue: SPR-13057
1 parent ca09b1f commit e7ea925

File tree

3 files changed

+95
-0
lines changed

3 files changed

+95
-0
lines changed

spring-core/src/test/java/org/springframework/core/annotation/AnnotationUtilsTests.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.springframework.core.Ordered;
3535
import org.springframework.core.annotation.subpackage.NonPublicAnnotatedClass;
3636
import org.springframework.stereotype.Component;
37+
import org.springframework.util.ClassUtils;
3738

3839
import static org.hamcrest.Matchers.*;
3940
import static org.junit.Assert.*;
@@ -609,6 +610,32 @@ public void synthesizeAnnotationWithAttributeAliases() throws Exception {
609610
assertEquals("actual value attribute: ", "/test", synthesizedWebMapping.value());
610611
}
611612

613+
/**
614+
* Fully reflection-based test that verifies support for
615+
* {@linkplain AnnotationUtils#synthesizeAnnotation synthesizing annotations}
616+
* across packages with non-public visibility of user types (e.g., a non-public
617+
* annotation that uses {@code @AliasFor}).
618+
*/
619+
@Test
620+
@SuppressWarnings("unchecked")
621+
public void synthesizeNonPublicAnnotationWithAttributeAliasesFromDifferentPackage() throws Exception {
622+
623+
Class<?> clazz =
624+
ClassUtils.forName("org.springframework.core.annotation.subpackage.NonPublicAliasedAnnotatedClass", null);
625+
Class<? extends Annotation> annotationType = (Class<? extends Annotation>)
626+
ClassUtils.forName("org.springframework.core.annotation.subpackage.NonPublicAliasedAnnotation", null);
627+
628+
Annotation annotation = clazz.getAnnotation(annotationType);
629+
assertNotNull(annotation);
630+
Annotation synthesizedAnnotation = synthesizeAnnotation(annotation);
631+
assertNotSame(annotation, synthesizedAnnotation);
632+
633+
assertNotNull(synthesizedAnnotation);
634+
assertEquals("name attribute: ", "test", getValue(synthesizedAnnotation, "name"));
635+
assertEquals("aliased path attribute: ", "/test", getValue(synthesizedAnnotation, "path"));
636+
assertEquals("aliased path attribute: ", "/test", getValue(synthesizedAnnotation, "value"));
637+
}
638+
612639
@Test
613640
public void synthesizeAnnotationWithAttributeAliasesInNestedAnnotations() throws Exception {
614641
Hierarchy hierarchy = TestCase.class.getAnnotation(Hierarchy.class);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2002-2015 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.core.annotation.subpackage;
18+
19+
/**
20+
* Class annotated with a non-public (i.e., package private) custom annotation
21+
* that uses {@code @AliasFor}.
22+
*
23+
* @author Sam Brannen
24+
* @since 4.2
25+
*/
26+
@NonPublicAliasedAnnotation(name = "test", path = "/test")
27+
class NonPublicAliasedAnnotatedClass {
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2002-2015 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.core.annotation.subpackage;
18+
19+
import java.lang.annotation.Retention;
20+
import java.lang.annotation.RetentionPolicy;
21+
22+
import org.springframework.core.annotation.AliasFor;
23+
24+
/**
25+
* Non-public mock of {@code org.springframework.web.bind.annotation.RequestMapping}.
26+
*
27+
* @author Sam Brannen
28+
* @since 4.2
29+
*/
30+
@Retention(RetentionPolicy.RUNTIME)
31+
@interface NonPublicAliasedAnnotation {
32+
33+
String name();
34+
35+
@AliasFor(attribute = "path")
36+
String value() default "";
37+
38+
@AliasFor(attribute = "value")
39+
String path() default "";
40+
}

0 commit comments

Comments
 (0)