Skip to content

Commit ec78165

Browse files
committed
Component scanning ignores attributes and meta-annotations on non-public annotations
Issue: SPR-11091 (cherry picked from commit 161819f)
1 parent e4fb72f commit ec78165

File tree

4 files changed

+76
-31
lines changed

4 files changed

+76
-31
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2002-2013 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 example.scannable;
18+
19+
import java.lang.annotation.Retention;
20+
import java.lang.annotation.RetentionPolicy;
21+
22+
public class CustomAnnotations {
23+
24+
@Retention(RetentionPolicy.RUNTIME)
25+
private @interface PrivateAnnotation {
26+
String value();
27+
}
28+
29+
@Retention(RetentionPolicy.RUNTIME)
30+
@PrivateAnnotation("special")
31+
public @interface SpecialAnnotation {
32+
}
33+
34+
}

spring-context/src/test/java/example/scannable/CustomComponent.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2007 the original author or authors.
2+
* Copyright 2002-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@
2828
@Target(ElementType.TYPE)
2929
@Retention(RetentionPolicy.RUNTIME)
3030
@Inherited
31+
@CustomAnnotations.SpecialAnnotation
3132
public @interface CustomComponent {
3233

3334
}

spring-context/src/test/java/example/scannable/MessageBean.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
2020
* @author Mark Fisher
2121
*/
2222
@CustomComponent
23+
@CustomAnnotations.SpecialAnnotation
2324
public class MessageBean {
2425

2526
private String message;
@@ -32,6 +33,7 @@ public MessageBean(String message) {
3233
this.message = message;
3334
}
3435

36+
@CustomAnnotations.SpecialAnnotation
3537
public String getMessage() {
3638
return this.message;
3739
}

spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationAttributesReadingVisitor.java

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.lang.reflect.Array;
2121
import java.lang.reflect.Field;
2222
import java.lang.reflect.Method;
23+
import java.lang.reflect.Modifier;
2324
import java.util.ArrayList;
2425
import java.util.LinkedHashSet;
2526
import java.util.List;
@@ -28,6 +29,7 @@
2829

2930
import org.apache.commons.logging.Log;
3031
import org.apache.commons.logging.LogFactory;
32+
3133
import org.springframework.asm.AnnotationVisitor;
3234
import org.springframework.asm.SpringAsmInfo;
3335
import org.springframework.asm.Type;
@@ -36,7 +38,6 @@
3638
import org.springframework.util.ObjectUtils;
3739
import org.springframework.util.ReflectionUtils;
3840

39-
4041
/**
4142
* @author Chris Beams
4243
* @author Juergen Hoeller
@@ -169,12 +170,11 @@ public RecursiveAnnotationAttributesVisitor(
169170
public final void visitEnd() {
170171
try {
171172
Class<?> annotationClass = this.classLoader.loadClass(this.annotationType);
172-
this.doVisitEnd(annotationClass);
173+
doVisitEnd(annotationClass);
173174
}
174175
catch (ClassNotFoundException ex) {
175-
this.logger.debug("Failed to classload type while reading annotation " +
176-
"metadata. This is a non-fatal error, but certain annotation " +
177-
"metadata may be unavailable.", ex);
176+
this.logger.debug("Failed to class-load type while reading annotation metadata. " +
177+
"This is a non-fatal error, but certain annotation metadata may be unavailable.", ex);
178178
}
179179
}
180180

@@ -183,26 +183,30 @@ protected void doVisitEnd(Class<?> annotationClass) {
183183
}
184184

185185
private void registerDefaultValues(Class<?> annotationClass) {
186-
// Check declared default values of attributes in the annotation type.
187-
Method[] annotationAttributes = annotationClass.getMethods();
188-
for (Method annotationAttribute : annotationAttributes) {
189-
String attributeName = annotationAttribute.getName();
190-
Object defaultValue = annotationAttribute.getDefaultValue();
191-
if (defaultValue != null && !this.attributes.containsKey(attributeName)) {
192-
if (defaultValue instanceof Annotation) {
193-
defaultValue = AnnotationAttributes.fromMap(
194-
AnnotationUtils.getAnnotationAttributes((Annotation)defaultValue, false, true));
195-
}
196-
else if (defaultValue instanceof Annotation[]) {
197-
Annotation[] realAnnotations = (Annotation[]) defaultValue;
198-
AnnotationAttributes[] mappedAnnotations = new AnnotationAttributes[realAnnotations.length];
199-
for (int i = 0; i < realAnnotations.length; i++) {
200-
mappedAnnotations[i] = AnnotationAttributes.fromMap(
201-
AnnotationUtils.getAnnotationAttributes(realAnnotations[i], false, true));
186+
// Only do further scanning for public annotations; we'd run into IllegalAccessExceptions
187+
// otherwise, and don't want to mess with accessibility in a SecurityManager environment.
188+
if (Modifier.isPublic(annotationClass.getModifiers())) {
189+
// Check declared default values of attributes in the annotation type.
190+
Method[] annotationAttributes = annotationClass.getMethods();
191+
for (Method annotationAttribute : annotationAttributes) {
192+
String attributeName = annotationAttribute.getName();
193+
Object defaultValue = annotationAttribute.getDefaultValue();
194+
if (defaultValue != null && !this.attributes.containsKey(attributeName)) {
195+
if (defaultValue instanceof Annotation) {
196+
defaultValue = AnnotationAttributes.fromMap(
197+
AnnotationUtils.getAnnotationAttributes((Annotation) defaultValue, false, true));
198+
}
199+
else if (defaultValue instanceof Annotation[]) {
200+
Annotation[] realAnnotations = (Annotation[]) defaultValue;
201+
AnnotationAttributes[] mappedAnnotations = new AnnotationAttributes[realAnnotations.length];
202+
for (int i = 0; i < realAnnotations.length; i++) {
203+
mappedAnnotations[i] = AnnotationAttributes.fromMap(
204+
AnnotationUtils.getAnnotationAttributes(realAnnotations[i], false, true));
205+
}
206+
defaultValue = mappedAnnotations;
202207
}
203-
defaultValue = mappedAnnotations;
208+
this.attributes.put(attributeName, defaultValue);
204209
}
205-
this.attributes.put(attributeName, defaultValue);
206210
}
207211
}
208212
}
@@ -251,12 +255,16 @@ private void registerMetaAnnotations(Class<?> annotationClass) {
251255
Set<String> metaAnnotationTypeNames = new LinkedHashSet<String>();
252256
for (Annotation metaAnnotation : annotationClass.getAnnotations()) {
253257
metaAnnotationTypeNames.add(metaAnnotation.annotationType().getName());
254-
if (!this.attributesMap.containsKey(metaAnnotation.annotationType().getName())) {
255-
this.attributesMap.put(metaAnnotation.annotationType().getName(),
256-
AnnotationUtils.getAnnotationAttributes(metaAnnotation, true, true));
257-
}
258-
for (Annotation metaMetaAnnotation : metaAnnotation.annotationType().getAnnotations()) {
259-
metaAnnotationTypeNames.add(metaMetaAnnotation.annotationType().getName());
258+
// Only do further scanning for public annotations; we'd run into IllegalAccessExceptions
259+
// otherwise, and don't want to mess with accessibility in a SecurityManager environment.
260+
if (Modifier.isPublic(metaAnnotation.annotationType().getModifiers())) {
261+
if (!this.attributesMap.containsKey(metaAnnotation.annotationType().getName())) {
262+
this.attributesMap.put(metaAnnotation.annotationType().getName(),
263+
AnnotationUtils.getAnnotationAttributes(metaAnnotation, true, true));
264+
}
265+
for (Annotation metaMetaAnnotation : metaAnnotation.annotationType().getAnnotations()) {
266+
metaAnnotationTypeNames.add(metaMetaAnnotation.annotationType().getName());
267+
}
260268
}
261269
}
262270
if (this.metaAnnotationMap != null) {

0 commit comments

Comments
 (0)