The <mvc:annotation-driven/>
元素隐式注册一个ExceptionHandlerExceptionResolver
豆。这个类有一个initExceptionHandlerAdviceCache()
扫描上下文中的 bean 以查找其类类型注释为的 bean 的方法@ControllerAdvice
.
它通过首先调用来做到这一点ControllerAdviceBean.findAnnotatedBeans(ApplicationContext) http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/method/ControllerAdviceBean.html#findAnnotatedBeans-org.springframework.context.ApplicationContext-。在内部,该方法使用ApplicationContext#getBeanDefinitionNames() http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/ListableBeanFactory.html#getBeanDefinitionNames--。该方法的 javadoc 指出
不考虑该工厂可能参与的任何层次结构
为了澄清这意味着什么。当你声明一个ContextLoaderListener
在您的部署描述符中,它加载我们所说的根或应用程序ApplicationContext
并使其可以在ServletContext
。当你随后声明一个DispatcherServlet
,它创建了自己的servlet ApplicationContext
并使用任何ApplicationContext
它发现在ServletContext
加载的属性ContextLoaderListener
作为该上下文的父级。层次结构看起来像这样
Root ApplicationContext // loaded by the ContextLoaderListener
|
Servlet ApplicationContext // loaded by the DispatcherServlet
Every ApplicationContext
可以访问父上下文中的 bean,但反之则不行。
上面的方法选择不使用父上下文中的bean,因此只能访问当前上下文中的beanApplicationContext
(BeanFactory
真的吗)。
因此,如果您的
<context:component-scan .../>
在根中声明ApplicationContext
正如我从名字中假设的那样app-config
,但是
<mvc:annotation-driven />
在servlet中声明ApplicationContext
,再次假设从mvc-config
,那么ExceptionHandlerExceptionResolver
寻找@ControllerAdvice
豆子将找不到任何。它正在 servlet 上下文中寻找 bean,但它们不在那里,而是在根上下文中。