From 4013fe03a579dbdd19d47fd240a493f034da284a Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 4 Dec 2014 17:56:01 +0100 Subject: [PATCH] Revised ControllerAdvice basePackages handling (based on package names instead of java.lang.Package) Issue: SPR-12506 --- .../web/method/ControllerAdviceBean.java | 152 +++++++++--------- 1 file changed, 73 insertions(+), 79 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/web/method/ControllerAdviceBean.java b/spring-web/src/main/java/org/springframework/web/method/ControllerAdviceBean.java index 4891ef6765..b9d4cb0e24 100644 --- a/spring-web/src/main/java/org/springframework/web/method/ControllerAdviceBean.java +++ b/spring-web/src/main/java/org/springframework/web/method/ControllerAdviceBean.java @@ -19,10 +19,9 @@ package org.springframework.web.method; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Arrays; +import java.util.LinkedHashSet; import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import java.util.Set; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryUtils; @@ -39,76 +38,77 @@ import org.springframework.web.bind.annotation.ControllerAdvice; * Encapsulates information about an {@linkplain ControllerAdvice @ControllerAdvice} * Spring-managed bean without necessarily requiring it to be instantiated. * - *

The {@link #findAnnotatedBeans(ApplicationContext)} method can be used to discover - * such beans. However, an {@code ControllerAdviceBean} may be created from - * any object, including ones without an {@code @ControllerAdvice}. + *

The {@link #findAnnotatedBeans(ApplicationContext)} method can be used to + * discover such beans. However, a {@code ControllerAdviceBean} may be created + * from any object, including ones without an {@code @ControllerAdvice}. * * @author Rossen Stoyanchev * @author Brian Clozel + * @author Juergen Hoeller * @since 3.2 */ public class ControllerAdviceBean implements Ordered { - private static final Log logger = LogFactory.getLog(ControllerAdviceBean.class); - private final Object bean; + private final BeanFactory beanFactory; + private final int order; - private final BeanFactory beanFactory; + private final Set basePackages; - private final List basePackages = new ArrayList(); + private final List> assignableTypes; - private final List> annotations = new ArrayList>(); + private final List> annotations; - private final List> assignableTypes = new ArrayList>(); + /** + * Create a {@code ControllerAdviceBean} using the given bean instance. + * @param bean the bean instance + */ + public ControllerAdviceBean(Object bean) { + this(bean, null); + } /** - * Create an instance using the given bean name. + * Create a {@code ControllerAdviceBean} using the given bean name. * @param beanName the name of the bean * @param beanFactory a BeanFactory that can be used later to resolve the bean */ public ControllerAdviceBean(String beanName, BeanFactory beanFactory) { - Assert.hasText(beanName, "Bean name must not be null"); - Assert.notNull(beanFactory, "BeanFactory must not be null"); - - if (!beanFactory.containsBean(beanName)) { - throw new IllegalArgumentException( - "BeanFactory [" + beanFactory + "] does not contain bean with name '" + beanName + "'"); - } - - this.bean = beanName; - this.beanFactory = beanFactory; - - Class beanType = this.beanFactory.getType(beanName); - this.order = initOrderFromBeanType(beanType); - - ControllerAdvice annotation = AnnotationUtils.findAnnotation(beanType,ControllerAdvice.class); - Assert.notNull(annotation, "BeanType [" + beanType.getName() + "] is not annotated @ControllerAdvice"); - - this.basePackages.addAll(initBasePackagesFromBeanType(beanType, annotation)); - this.annotations.addAll(Arrays.asList(annotation.annotations())); - this.assignableTypes.addAll(Arrays.asList(annotation.assignableTypes())); + this((Object) beanName, beanFactory); } - /** - * Create an instance using the given bean instance. - * @param bean the bean - */ - public ControllerAdviceBean(Object bean) { - Assert.notNull(bean, "Bean must not be null"); + private ControllerAdviceBean(Object bean, BeanFactory beanFactory) { this.bean = bean; - this.order = initOrderFromBean(bean); - - Class beanType = bean.getClass(); - ControllerAdvice annotation = AnnotationUtils.findAnnotation(beanType,ControllerAdvice.class); - Assert.notNull(annotation, "Bean type [" + beanType.getName() + "] is not annotated @ControllerAdvice"); + this.beanFactory = beanFactory; + Class beanType; + + if (bean instanceof String) { + String beanName = (String) bean; + Assert.hasText(beanName, "Bean name must not be null"); + Assert.notNull(beanFactory, "BeanFactory must not be null"); + if (!beanFactory.containsBean(beanName)) { + throw new IllegalArgumentException("BeanFactory [" + beanFactory + + "] does not contain specified controller advice bean '" + beanName + "'"); + } + beanType = this.beanFactory.getType(beanName); + this.order = initOrderFromBeanType(beanType); + } + else { + Assert.notNull(bean, "Bean must not be null"); + beanType = bean.getClass(); + this.order = initOrderFromBean(bean); + } - this.basePackages.addAll(initBasePackagesFromBeanType(beanType, annotation)); - this.annotations.addAll(Arrays.asList(annotation.annotations())); - this.assignableTypes.addAll(Arrays.asList(annotation.assignableTypes())); - this.beanFactory = null; + ControllerAdvice annotation = AnnotationUtils.findAnnotation(beanType, ControllerAdvice.class); + if (annotation == null) { + throw new IllegalArgumentException( + "Bean type [" + beanType.getName() + "] is not annotated as @ControllerAdvice"); + } + this.basePackages = initBasePackages(annotation); + this.assignableTypes = Arrays.asList(annotation.assignableTypes()); + this.annotations = Arrays.asList(annotation.annotations()); } @@ -150,6 +150,11 @@ public class ControllerAdviceBean implements Ordered { return true; } else if (beanType != null) { + for (String basePackage : this.basePackages) { + if (ClassUtils.getPackageName(beanType).startsWith(basePackage)) { + return true; + } + } for (Class clazz : this.assignableTypes) { if (ClassUtils.isAssignable(clazz, beanType)) { return true; @@ -160,25 +165,25 @@ public class ControllerAdviceBean implements Ordered { return true; } } - String packageName = beanType.getPackage().getName(); - for (Package basePackage : this.basePackages) { - if (packageName.startsWith(basePackage.getName())) { - return true; - } - } } return false; } private boolean hasSelectors() { - return (!this.basePackages.isEmpty() || !this.annotations.isEmpty() || !this.assignableTypes.isEmpty()); + return (!this.basePackages.isEmpty() || !this.assignableTypes.isEmpty() || !this.annotations.isEmpty()); } @Override public boolean equals(Object other) { - return (this == other || - (other instanceof ControllerAdviceBean && this.bean.equals(((ControllerAdviceBean) other).bean))); + if (this == other) { + return true; + } + if (!(other instanceof ControllerAdviceBean)) { + return false; + } + ControllerAdviceBean otherAdvice = (ControllerAdviceBean) other; + return (this.bean.equals(otherAdvice.bean) && this.beanFactory == otherAdvice.beanFactory); } @Override @@ -215,32 +220,21 @@ public class ControllerAdviceBean implements Ordered { return OrderUtils.getOrder(beanType, Ordered.LOWEST_PRECEDENCE); } - private static List initBasePackagesFromBeanType(Class beanType, ControllerAdvice annotation) { - List basePackages = new ArrayList(); - List basePackageNames = new ArrayList(); - basePackageNames.addAll(Arrays.asList(annotation.value())); - basePackageNames.addAll(Arrays.asList(annotation.basePackages())); - for (String pkgName : basePackageNames) { - if (StringUtils.hasText(pkgName)) { - Package pkg = Package.getPackage(pkgName); - if (pkg != null) { - basePackages.add(pkg); - } - else { - logger.warn("Package [" + pkgName + "] was not found, see [" + beanType.getName() + "]"); - } + private static Set initBasePackages(ControllerAdvice annotation) { + Set basePackages = new LinkedHashSet(); + for (String basePackage : annotation.value()) { + if (StringUtils.hasText(basePackage)) { + basePackages.add(basePackage); } } - for (Class markerClass : annotation.basePackageClasses()) { - Package pack = markerClass.getPackage(); - if (pack != null) { - basePackages.add(pack); - } - else { - logger.warn("Package was not found for class [" + markerClass.getName() + - "], see [" + beanType.getName() + "]"); + for (String basePackage : annotation.basePackages()) { + if (StringUtils.hasText(basePackage)) { + basePackages.add(basePackage); } } + for (Class markerClass : annotation.basePackageClasses()) { + basePackages.add(ClassUtils.getPackageName(markerClass)); + } return basePackages; }