首先,如果你是:

1.初学者,通过学习Spring实战来学习Spring框架的
2.通过继承AbstractAnnotationConfigDispatcherServletInitializer类来创建DispatcherServlet的

3.你遇到了这样的问题:自己创建的或者是外部的由@Bean+@Configuration来声名的bean无法被装配到spring容器中,自己无法调用这些bean

经过几个小时的排查,终于找到了原因所在:

AbstractAnnotationConfigDispatcherServletInitializer这个类的作用:
1.它帮你创建了DispatcherServlet
2.它可以帮你配置Servlet Application Context
3.它可以帮你配置Root Application Context

第一个作用很好理解,因为它实现了WebApplicationIntializer接口,而这个接口又被委托了创建Servlet的责任

我们主要来分析第二个和第三个作用,

首先,Servlet Application Context是什么?创建了之后有什么用?
这里引入官方文档的说明:在这里插入图片描述
上面说Servlet Application Context是要提供给DispatcherServlet的组件,也就是MVC的一些组件,controllers啊,一些resolvers啊,等等。
在这里插入图片描述
它是通过AbstractAnnotationConfigDispatcherServletInitializer的一个名叫getServletConfigClasses()的方法实现的,这个方法的返回类型为Class<?>[ ],也就是说,你要把装配了或者是扫描了MVC的组件的类放到这个方法中去,它就会帮你配置好DispatcherServlet和MVC组件间的收发关系了,而这些组件会被放到哪里呢?请看继续看下去

其次,我们来看Root Application Context,这是个什么东西呢?上文档!
在这里插入图片描述
上面说root application context是用来提供给ContextLoaderListener的,而ContextLoaderListener这个类是用来干什么的呢? 文档说 ,它是用来包含中间层服务、数据资源等,也就是说,这个ContextLoaderListener类的作用就是需要扫描或者自个儿装配关于中间层服务、数据资源 的bean们。

问题来了,这些bean会被装配到哪呢? 他们会被装配到名为 root application context的地方去(也就是spring容器的根目录处)

那这个根目录是相对什么来说是根目录呢?文档上说,它是DispatcherServlet application contexts的父容器,也就是存放MVC组件容器的父容器, 也就是说, root application context 是mvc application context(用servlet application context的话感觉会怪怪的。。)的父容器,他们之间是父子关系。

经过我测试,放在getRootConfigClasses()方法中的承担ContextLoaderListener(即负责装配中间组件、数据资源组件)责任的类,必须要放在当前包内才可以!因此,通常是采用扫描的方法来将DAO层、Service层的一些bean装进root application context中去的。

总结一下,引起注解无效的原因是,你需要将你的非mvc组件的component通过ContextLoaderListener类的ComponentScaner来扫描进root application context。

欢迎各位大佬指出错误!!!

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐