Skip to content

Commit 978adbd

Browse files
committed
Avoid duplicate lookups of @ControllerAdvice annotations
See gh-23163
1 parent ed6fbdd commit 978adbd

File tree

1 file changed

+33
-10
lines changed

1 file changed

+33
-10
lines changed

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

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -85,20 +85,37 @@ public ControllerAdviceBean(Object bean) {
8585
}
8686

8787
/**
88-
* Create a {@code ControllerAdviceBean} using the given bean name.
88+
* Create a {@code ControllerAdviceBean} using the given bean name and
89+
* {@code BeanFactory}.
8990
* @param beanName the name of the bean
9091
* @param beanFactory a {@code BeanFactory} to retrieve the bean type initially
9192
* and later to resolve the actual bean
9293
*/
9394
public ControllerAdviceBean(String beanName, BeanFactory beanFactory) {
95+
this(beanName, beanFactory, null);
96+
}
97+
98+
/**
99+
* Create a {@code ControllerAdviceBean} using the given bean name,
100+
* {@code BeanFactory}, and {@link ControllerAdvice @ControllerAdvice}
101+
* annotation.
102+
* @param beanName the name of the bean
103+
* @param beanFactory a {@code BeanFactory} to retrieve the bean type initially
104+
* and later to resolve the actual bean
105+
* @param controllerAdvice the {@code @ControllerAdvice} annotation for the
106+
* bean, or {@code null} if not yet retrieved
107+
* @since 5.2
108+
*/
109+
public ControllerAdviceBean(String beanName, BeanFactory beanFactory, @Nullable ControllerAdvice controllerAdvice) {
94110
Assert.hasText(beanName, "Bean name must contain text");
95111
Assert.notNull(beanFactory, "BeanFactory must not be null");
96112
Assert.isTrue(beanFactory.containsBean(beanName), () -> "BeanFactory [" + beanFactory
97113
+ "] does not contain specified controller advice bean '" + beanName + "'");
98114

99115
this.beanOrName = beanName;
100116
this.beanType = getBeanType(beanName, beanFactory);
101-
this.beanTypePredicate = createBeanTypePredicate(this.beanType);
117+
this.beanTypePredicate = (controllerAdvice != null ? createBeanTypePredicate(controllerAdvice)
118+
: createBeanTypePredicate(this.beanType));
102119
this.beanFactory = beanFactory;
103120
this.order = initOrderFromBeanType(this.beanType);
104121
}
@@ -186,8 +203,11 @@ public String toString() {
186203
public static List<ControllerAdviceBean> findAnnotatedBeans(ApplicationContext context) {
187204
List<ControllerAdviceBean> adviceBeans = new ArrayList<>();
188205
for (String name : BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, Object.class)) {
189-
if (context.findAnnotationOnBean(name, ControllerAdvice.class) != null) {
190-
adviceBeans.add(new ControllerAdviceBean(name, context));
206+
ControllerAdvice controllerAdvice = context.findAnnotationOnBean(name, ControllerAdvice.class);
207+
if (controllerAdvice != null) {
208+
// Use the @ControllerAdvice annotation found by findAnnotationOnBean()
209+
// in order to avoid a subsequent lookup of the same annotation.
210+
adviceBeans.add(new ControllerAdviceBean(name, context, controllerAdvice));
191211
}
192212
}
193213
return adviceBeans;
@@ -199,15 +219,18 @@ private static Class<?> getBeanType(String beanName, BeanFactory beanFactory) {
199219
}
200220

201221
private static HandlerTypePredicate createBeanTypePredicate(Class<?> beanType) {
202-
ControllerAdvice annotation = (beanType != null ?
222+
ControllerAdvice controllerAdvice = (beanType != null ?
203223
AnnotatedElementUtils.findMergedAnnotation(beanType, ControllerAdvice.class) : null);
224+
return createBeanTypePredicate(controllerAdvice);
225+
}
204226

205-
if (annotation != null) {
227+
private static HandlerTypePredicate createBeanTypePredicate(ControllerAdvice controllerAdvice) {
228+
if (controllerAdvice != null) {
206229
return HandlerTypePredicate.builder()
207-
.basePackage(annotation.basePackages())
208-
.basePackageClass(annotation.basePackageClasses())
209-
.assignableType(annotation.assignableTypes())
210-
.annotation(annotation.annotations())
230+
.basePackage(controllerAdvice.basePackages())
231+
.basePackageClass(controllerAdvice.basePackageClasses())
232+
.assignableType(controllerAdvice.assignableTypes())
233+
.annotation(controllerAdvice.annotations())
211234
.build();
212235
}
213236
return HandlerTypePredicate.forAnyHandlerType();

0 commit comments

Comments
 (0)