Skip to content

Commit 4013fe0

Browse files
committed
Revised ControllerAdvice basePackages handling (based on package names instead of java.lang.Package)
Issue: SPR-12506
1 parent ad65119 commit 4013fe0

File tree

1 file changed

+73
-79
lines changed

1 file changed

+73
-79
lines changed

spring-web/src/main/java/org/springframework/web/method/ControllerAdviceBean.java

+73-79
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,9 @@
1919
import java.lang.annotation.Annotation;
2020
import java.util.ArrayList;
2121
import java.util.Arrays;
22+
import java.util.LinkedHashSet;
2223
import java.util.List;
23-
24-
import org.apache.commons.logging.Log;
25-
import org.apache.commons.logging.LogFactory;
24+
import java.util.Set;
2625

2726
import org.springframework.beans.factory.BeanFactory;
2827
import org.springframework.beans.factory.BeanFactoryUtils;
@@ -39,76 +38,77 @@
3938
* Encapsulates information about an {@linkplain ControllerAdvice @ControllerAdvice}
4039
* Spring-managed bean without necessarily requiring it to be instantiated.
4140
*
42-
* <p>The {@link #findAnnotatedBeans(ApplicationContext)} method can be used to discover
43-
* such beans. However, an {@code ControllerAdviceBean} may be created from
44-
* any object, including ones without an {@code @ControllerAdvice}.
41+
* <p>The {@link #findAnnotatedBeans(ApplicationContext)} method can be used to
42+
* discover such beans. However, a {@code ControllerAdviceBean} may be created
43+
* from any object, including ones without an {@code @ControllerAdvice}.
4544
*
4645
* @author Rossen Stoyanchev
4746
* @author Brian Clozel
47+
* @author Juergen Hoeller
4848
* @since 3.2
4949
*/
5050
public class ControllerAdviceBean implements Ordered {
5151

52-
private static final Log logger = LogFactory.getLog(ControllerAdviceBean.class);
53-
5452
private final Object bean;
5553

54+
private final BeanFactory beanFactory;
55+
5656
private final int order;
5757

58-
private final BeanFactory beanFactory;
58+
private final Set<String> basePackages;
5959

60-
private final List<Package> basePackages = new ArrayList<Package>();
60+
private final List<Class<?>> assignableTypes;
6161

62-
private final List<Class<? extends Annotation>> annotations = new ArrayList<Class<? extends Annotation>>();
62+
private final List<Class<? extends Annotation>> annotations;
6363

64-
private final List<Class<?>> assignableTypes = new ArrayList<Class<?>>();
6564

65+
/**
66+
* Create a {@code ControllerAdviceBean} using the given bean instance.
67+
* @param bean the bean instance
68+
*/
69+
public ControllerAdviceBean(Object bean) {
70+
this(bean, null);
71+
}
6672

6773
/**
68-
* Create an instance using the given bean name.
74+
* Create a {@code ControllerAdviceBean} using the given bean name.
6975
* @param beanName the name of the bean
7076
* @param beanFactory a BeanFactory that can be used later to resolve the bean
7177
*/
7278
public ControllerAdviceBean(String beanName, BeanFactory beanFactory) {
73-
Assert.hasText(beanName, "Bean name must not be null");
74-
Assert.notNull(beanFactory, "BeanFactory must not be null");
75-
76-
if (!beanFactory.containsBean(beanName)) {
77-
throw new IllegalArgumentException(
78-
"BeanFactory [" + beanFactory + "] does not contain bean with name '" + beanName + "'");
79-
}
80-
81-
this.bean = beanName;
82-
this.beanFactory = beanFactory;
83-
84-
Class<?> beanType = this.beanFactory.getType(beanName);
85-
this.order = initOrderFromBeanType(beanType);
86-
87-
ControllerAdvice annotation = AnnotationUtils.findAnnotation(beanType,ControllerAdvice.class);
88-
Assert.notNull(annotation, "BeanType [" + beanType.getName() + "] is not annotated @ControllerAdvice");
89-
90-
this.basePackages.addAll(initBasePackagesFromBeanType(beanType, annotation));
91-
this.annotations.addAll(Arrays.asList(annotation.annotations()));
92-
this.assignableTypes.addAll(Arrays.asList(annotation.assignableTypes()));
79+
this((Object) beanName, beanFactory);
9380
}
9481

95-
/**
96-
* Create an instance using the given bean instance.
97-
* @param bean the bean
98-
*/
99-
public ControllerAdviceBean(Object bean) {
100-
Assert.notNull(bean, "Bean must not be null");
82+
private ControllerAdviceBean(Object bean, BeanFactory beanFactory) {
10183
this.bean = bean;
102-
this.order = initOrderFromBean(bean);
103-
104-
Class<?> beanType = bean.getClass();
105-
ControllerAdvice annotation = AnnotationUtils.findAnnotation(beanType,ControllerAdvice.class);
106-
Assert.notNull(annotation, "Bean type [" + beanType.getName() + "] is not annotated @ControllerAdvice");
84+
this.beanFactory = beanFactory;
85+
Class<?> beanType;
86+
87+
if (bean instanceof String) {
88+
String beanName = (String) bean;
89+
Assert.hasText(beanName, "Bean name must not be null");
90+
Assert.notNull(beanFactory, "BeanFactory must not be null");
91+
if (!beanFactory.containsBean(beanName)) {
92+
throw new IllegalArgumentException("BeanFactory [" + beanFactory +
93+
"] does not contain specified controller advice bean '" + beanName + "'");
94+
}
95+
beanType = this.beanFactory.getType(beanName);
96+
this.order = initOrderFromBeanType(beanType);
97+
}
98+
else {
99+
Assert.notNull(bean, "Bean must not be null");
100+
beanType = bean.getClass();
101+
this.order = initOrderFromBean(bean);
102+
}
107103

108-
this.basePackages.addAll(initBasePackagesFromBeanType(beanType, annotation));
109-
this.annotations.addAll(Arrays.asList(annotation.annotations()));
110-
this.assignableTypes.addAll(Arrays.asList(annotation.assignableTypes()));
111-
this.beanFactory = null;
104+
ControllerAdvice annotation = AnnotationUtils.findAnnotation(beanType, ControllerAdvice.class);
105+
if (annotation == null) {
106+
throw new IllegalArgumentException(
107+
"Bean type [" + beanType.getName() + "] is not annotated as @ControllerAdvice");
108+
}
109+
this.basePackages = initBasePackages(annotation);
110+
this.assignableTypes = Arrays.asList(annotation.assignableTypes());
111+
this.annotations = Arrays.asList(annotation.annotations());
112112
}
113113

114114

@@ -150,6 +150,11 @@ public boolean isApplicableToBeanType(Class<?> beanType) {
150150
return true;
151151
}
152152
else if (beanType != null) {
153+
for (String basePackage : this.basePackages) {
154+
if (ClassUtils.getPackageName(beanType).startsWith(basePackage)) {
155+
return true;
156+
}
157+
}
153158
for (Class<?> clazz : this.assignableTypes) {
154159
if (ClassUtils.isAssignable(clazz, beanType)) {
155160
return true;
@@ -160,25 +165,25 @@ else if (beanType != null) {
160165
return true;
161166
}
162167
}
163-
String packageName = beanType.getPackage().getName();
164-
for (Package basePackage : this.basePackages) {
165-
if (packageName.startsWith(basePackage.getName())) {
166-
return true;
167-
}
168-
}
169168
}
170169
return false;
171170
}
172171

173172
private boolean hasSelectors() {
174-
return (!this.basePackages.isEmpty() || !this.annotations.isEmpty() || !this.assignableTypes.isEmpty());
173+
return (!this.basePackages.isEmpty() || !this.assignableTypes.isEmpty() || !this.annotations.isEmpty());
175174
}
176175

177176

178177
@Override
179178
public boolean equals(Object other) {
180-
return (this == other ||
181-
(other instanceof ControllerAdviceBean && this.bean.equals(((ControllerAdviceBean) other).bean)));
179+
if (this == other) {
180+
return true;
181+
}
182+
if (!(other instanceof ControllerAdviceBean)) {
183+
return false;
184+
}
185+
ControllerAdviceBean otherAdvice = (ControllerAdviceBean) other;
186+
return (this.bean.equals(otherAdvice.bean) && this.beanFactory == otherAdvice.beanFactory);
182187
}
183188

184189
@Override
@@ -215,32 +220,21 @@ private static int initOrderFromBeanType(Class<?> beanType) {
215220
return OrderUtils.getOrder(beanType, Ordered.LOWEST_PRECEDENCE);
216221
}
217222

218-
private static List<Package> initBasePackagesFromBeanType(Class<?> beanType, ControllerAdvice annotation) {
219-
List<Package> basePackages = new ArrayList<Package>();
220-
List<String> basePackageNames = new ArrayList<String>();
221-
basePackageNames.addAll(Arrays.asList(annotation.value()));
222-
basePackageNames.addAll(Arrays.asList(annotation.basePackages()));
223-
for (String pkgName : basePackageNames) {
224-
if (StringUtils.hasText(pkgName)) {
225-
Package pkg = Package.getPackage(pkgName);
226-
if (pkg != null) {
227-
basePackages.add(pkg);
228-
}
229-
else {
230-
logger.warn("Package [" + pkgName + "] was not found, see [" + beanType.getName() + "]");
231-
}
223+
private static Set<String> initBasePackages(ControllerAdvice annotation) {
224+
Set<String> basePackages = new LinkedHashSet<String>();
225+
for (String basePackage : annotation.value()) {
226+
if (StringUtils.hasText(basePackage)) {
227+
basePackages.add(basePackage);
232228
}
233229
}
234-
for (Class<?> markerClass : annotation.basePackageClasses()) {
235-
Package pack = markerClass.getPackage();
236-
if (pack != null) {
237-
basePackages.add(pack);
238-
}
239-
else {
240-
logger.warn("Package was not found for class [" + markerClass.getName() +
241-
"], see [" + beanType.getName() + "]");
230+
for (String basePackage : annotation.basePackages()) {
231+
if (StringUtils.hasText(basePackage)) {
232+
basePackages.add(basePackage);
242233
}
243234
}
235+
for (Class<?> markerClass : annotation.basePackageClasses()) {
236+
basePackages.add(ClassUtils.getPackageName(markerClass));
237+
}
244238
return basePackages;
245239
}
246240

0 commit comments

Comments
 (0)