From 77e75fdf878d5a472e5279535899ffa2212943bd Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 1 Aug 2018 12:18:10 +0200 Subject: [PATCH] Avoid synthesizable annotation creation for @Bean/@Scope on scanning Includes consistent (non-)use of AnnotationUtils/AnnotatedElementUtils. Issue: SPR-16933 --- .../annotation/BeanAnnotationHelper.java | 11 ++++---- .../annotation/AnnotatedElementUtils.java | 18 ++++++------- .../AnnotationAttributesReadingVisitor.java | 25 ++++++++++++------- .../annotation/ResponseBodyResultHandler.java | 16 ++++++------ 4 files changed, 37 insertions(+), 33 deletions(-) diff --git a/spring-context/src/main/java/org/springframework/context/annotation/BeanAnnotationHelper.java b/spring-context/src/main/java/org/springframework/context/annotation/BeanAnnotationHelper.java index b28ab0492b..c4afe22325 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/BeanAnnotationHelper.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/BeanAnnotationHelper.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2018 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. @@ -36,13 +36,14 @@ class BeanAnnotationHelper { public static String determineBeanNameFor(Method beanMethod) { // By default, the bean name is the name of the @Bean-annotated method String beanName = beanMethod.getName(); - // Check to see if the user has explicitly set a custom bean name... Bean bean = AnnotatedElementUtils.findMergedAnnotation(beanMethod, Bean.class); - if (bean != null && bean.name().length > 0) { - beanName = bean.name()[0]; + if (bean != null) { + String[] names = bean.name(); + if (names.length > 0) { + beanName = names[0]; + } } - return beanName; } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java index 9ce163be5b..776a2f981b 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java @@ -585,22 +585,20 @@ public class AnnotatedElementUtils { * attributes of the same name from higher levels, and * {@link AliasFor @AliasFor} semantics are fully supported, both * within a single annotation and within the annotation hierarchy. - *

In contrast to {@link #getAllAnnotationAttributes}, the search - * algorithm used by this method will stop searching the annotation - * hierarchy once the first annotation of the specified - * {@code annotationType} has been found. As a consequence, additional - * annotations of the specified {@code annotationType} will be ignored. + *

In contrast to {@link #getAllAnnotationAttributes}, the search algorithm + * used by this method will stop searching the annotation hierarchy once the + * first annotation of the specified {@code annotationType} has been found. + * As a consequence, additional annotations of the specified + * {@code annotationType} will be ignored. *

This method follows find semantics as described in the * {@linkplain AnnotatedElementUtils class-level javadoc}. * @param element the annotated element * @param annotationType the annotation type to find * @param classValuesAsString whether to convert Class references into * Strings or to preserve them as Class references - * @param nestedAnnotationsAsMap whether to convert nested Annotation - * instances into {@code AnnotationAttributes} maps or to preserve them - * as Annotation instances - * @return the merged {@code AnnotationAttributes}, or {@code null} if - * not found + * @param nestedAnnotationsAsMap whether to convert nested Annotation instances into + * {@code AnnotationAttributes} maps or to preserve them as Annotation instances + * @return the merged {@code AnnotationAttributes}, or {@code null} if not found * @since 4.2 * @see #findMergedAnnotation(AnnotatedElement, Class) * @see #getMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean) diff --git a/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationAttributesReadingVisitor.java b/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationAttributesReadingVisitor.java index 1e8561afbb..694e6f60c1 100644 --- a/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationAttributesReadingVisitor.java +++ b/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationAttributesReadingVisitor.java @@ -74,20 +74,27 @@ final class AnnotationAttributesReadingVisitor extends RecursiveAnnotationAttrib attributeList.add(0, this.attributes); } if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotationClass.getName())) { - Set visited = new LinkedHashSet<>(); - Annotation[] metaAnnotations = AnnotationUtils.getAnnotations(annotationClass); - if (!ObjectUtils.isEmpty(metaAnnotations)) { - for (Annotation metaAnnotation : metaAnnotations) { - if (!AnnotationUtils.isInJavaLangAnnotationPackage(metaAnnotation)) { + try { + Annotation[] metaAnnotations = annotationClass.getAnnotations(); + if (!ObjectUtils.isEmpty(metaAnnotations)) { + Set visited = new LinkedHashSet<>(); + for (Annotation metaAnnotation : metaAnnotations) { recursivelyCollectMetaAnnotations(visited, metaAnnotation); } + if (!visited.isEmpty()) { + Set metaAnnotationTypeNames = new LinkedHashSet<>(visited.size()); + for (Annotation ann : visited) { + metaAnnotationTypeNames.add(ann.annotationType().getName()); + } + this.metaAnnotationMap.put(annotationClass.getName(), metaAnnotationTypeNames); + } } } - Set metaAnnotationTypeNames = new LinkedHashSet<>(visited.size()); - for (Annotation ann : visited) { - metaAnnotationTypeNames.add(ann.annotationType().getName()); + catch (Throwable ex) { + if (logger.isDebugEnabled()) { + logger.debug("Failed to introspect meta-annotations on " + annotationClass + ": " + ex); + } } - this.metaAnnotationMap.put(annotationClass.getName(), metaAnnotationTypeNames); } } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseBodyResultHandler.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseBodyResultHandler.java index df57b638f8..be3a21c48b 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseBodyResultHandler.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseBodyResultHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -22,7 +22,7 @@ import reactor.core.publisher.Mono; import org.springframework.core.MethodParameter; import org.springframework.core.ReactiveAdapterRegistry; -import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.http.codec.HttpMessageWriter; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.reactive.HandlerResult; @@ -53,9 +53,7 @@ public class ResponseBodyResultHandler extends AbstractMessageWriterResultHandle * @param writers writers for serializing to the response body * @param resolver to determine the requested content type */ - public ResponseBodyResultHandler(List> writers, - RequestedContentTypeResolver resolver) { - + public ResponseBodyResultHandler(List> writers, RequestedContentTypeResolver resolver) { this(writers, resolver, ReactiveAdapterRegistry.getSharedInstance()); } @@ -75,10 +73,10 @@ public class ResponseBodyResultHandler extends AbstractMessageWriterResultHandle @Override public boolean supports(HandlerResult result) { - MethodParameter parameter = result.getReturnTypeSource(); - Class containingClass = parameter.getContainingClass(); - return (AnnotationUtils.findAnnotation(containingClass, ResponseBody.class) != null || - parameter.getMethodAnnotation(ResponseBody.class) != null); + MethodParameter returnType = result.getReturnTypeSource(); + Class containingClass = returnType.getContainingClass(); + return (AnnotatedElementUtils.hasAnnotation(containingClass, ResponseBody.class) || + returnType.hasMethodAnnotation(ResponseBody.class)); } @Override