首页 > 编程知识 正文

如何阅读spring源码,springmvc源码分析

时间:2023-05-05 07:53:07 阅读:51772 作者:512

一、概述对于第一次查看spring源代码的人来说,spring项目的源代码为: spring-beans、spring-context、spring-core、spring-aop、spring-core

因为spring是IOC容器或bean的容器,所以有些人可能认为从spring-beans的角度来看,spring需要了解如何从xml文件配置中获取需要创建的bean的信息此外,BeanFactory、FactoryBean、Environment和PropertySource等接口是抽象的、难以理解的,因此容易感到无聊,甚至放弃。 换个思路,从能接触到的角度开始吧。 也就是说,我们通常使用spring-mvc进行web开发。 例如,@Controller,@RequestMapping就再熟悉不过了。 如您在spring-mvc项目中所知,通常需要在web.xml文件中设置ContextLoaderListener、contextConfigLocation和DispatcherServlet。 许多人可能从internet发送复制配置,或者知道contextConfigLocation是指定spring配置文件的位置。 dispatcher servlet是接收所有请求的前端控制器,必须通过指定“/”来监听所有URL中带有“/”的请求,但在spring源代码中必须指定“/” 另外,我们的web项目通常部署在类似tomcat的web容器中,那么tomcat和spring有什么关系呢? 所以我们可以带着这些问题通过查看spring源代码找到答案。 所以我推荐从spring-mvc上查看spring源代码。 因为这是我们经常使用的简单易懂的模块,所以我们会一个接一个地揭下它,找出它和spring-context、spring-beans、spring-aop等的关系。 如果您真的对JavaWeb开发感兴趣,或者您很容易阅读spring源代码,请查看servlet规范和Tomcat设计以及Tomcat请求处理工作流。 我现在也在结合这两个方面来看,也可以看我的Tomcat源代码分析系列。 二. servlet规范servlet规范被称为web容器,诸如servlet容器或tomcat,其中在中执行的每个APP应用在一个servlet上下文中表示,并且在web容器中包括多个servlet上下文这意味着可以在web容器中运行多个web APP应用程序。 正如tomcat的webapp目录中所示,每个war包都支持一个webapp应用程序,它在tomcat启动时解压缩war包并启动相关的APP应用程序。 web容器启动后,web APP应用程序将初始化。 也就是说,可以创建ServletContext对象,加载分析web.xml文件,获取该APP应用程序的Filters、Listener和Servlet等组件的配置,然后创建对象实例, 将web容器作为ServletContext的属性存储在Servlet中,然后web容器在接收到客户端的请求时,会根据请求信息匹配处理该请求的Servlet,并在将处理传递给Servlet之前对其进行配置了解web容器的启动并接受客户端的请求有什么用呢? 这里需要回顾一下我们的spring项目。 我们日常开发的不是直接与web容器交互,如直接接触spring相关组件,将其制成war包,然后复制到tomcat的webapp目录中。 根据以上分析的结果,实际上spring项目与web容器中的ServletContext相对应,因此在创建和初始化ServletContext对象时,包含@Controller和@RequestMapping注释需要触发spring相关组件创建和初始化的机制三.监听器侦听器机制: contextloaderlistener servlet规范使用监听器侦听器机制来填充web容器一个重要的生命周期侦听器是ServletContextListener。 当web容器创建和初始化ServletContext时,将生成ServletContextEvent事件。 此事件包含对ServletContextEvent的引用。

然后传递给在此ServletContext中注册的监听程序ServletContextListener (由web.xml配置)。 ServletContextListener在其contextInitialized方法中定义处理逻辑。 接口定义如下:/* * * implementationsofthisinterfacereceivenotificationsaboutchangesthis

are part of. To receive * notification events, the implementation class must be configured in the * deployment descriptor for the web application. * * @see ServletContextEvent * @since v 2.3 */public interface ServletContextListener extends EventListener { /** ** Notification that the web application initialization process is starting. * All ServletContextListeners are notified of context initialization before * any filter or servlet in the web application is initialized. * @param sce Information about the ServletContext that was initialized */ public void contextInitialized(ServletContextEvent sce); /** ** Notification that the servlet context is about to be shut down. All * servlets and filters have been destroy()ed before any * ServletContextListeners are notified of context destruction. * @param sce Information about the ServletContext that was destroyed */ public void contextDestroyed(ServletContextEvent sce);} 从contextInitialized的注释可知:通知所有的ServletContextListeners,当前的web应用正在启动,而且这些ServletContextListeners是在Filters和Servlets创建之前接收到通知的。所以在这个时候,web应用还不能接收请求,故可以在这里完成底层处理请求的组件的加载,这样等之后接收请求的Filters和Servlets创建时,则可以使用这些创建好的组件了。spring相关的bean就是这里所说的底层处理请求的组件,如数据库连接池,数据库事务管理器等。ContextLoaderListener:spring-web包的ContextLoaderListener就是一个ServletContextListener的实现类。ContextLoaderListener主要用来获取spring项目的整体配置信息,并创建对应的WebApplicationContext来保存bean的信息,以及创建这些bean的对象实例。默认去WEB-INF下加载applicationContext.xml配置,如果applicationContext.xml放在其他位置,或者使用其他不同的名称,或者使用多个xml文件,则与指定contextConfigLocation。具体spring源码的实现过程后续文章详细分析。<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!-- 修改配置文件路径 --><context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/applicationContext.xml</param-value></context-param> 四、DispatcherServlet:前端控制器 在web容器中,web.xml中的加载顺序:context-param -> listener -> filter -> servlet。其中ContextLoaderListener是属于listener阶段。我们通常需要在项目的web.xml中配置一个DispatcherServlet,并配置拦截包含“/”路径的请求,即拦截所有请求。这样在web容器启动应用时,在servlet阶段会创建这个servlet,由Servlet规范中servlet的生命周期方法可知:public interface Servlet { void init(ServletConfig var1) throws ServletException; ServletConfig getServletConfig(); void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException; String getServletInfo(); void destroy();} web容器在创建这个servlet的时候,会调用其init方法,故可以在DispatcherServlet的init方法中定义初始化逻辑,核心实现了创建DispatcherServlet自身的一个WebApplicationContext,注意在spring中每个servlet可以包含一个独立的WebApplicationContext来维护自身的组件,而上面通过ContextLoaderListener创建的WebApplicationContext为共有的,通常也是最顶层,即root WebApplicationContext,servlet的WebApplicationContext可以通过setParent方法设值到自身的一个属性。DispatcherServlet默认是加载WEB-INF下面的“servletName”-servlet.xml,来获取配置信息的,也可以与ContextLoaderListener一样通过contextLoaderConfig来指定位置。DispatcherServlet具体的源码设计在之后文章详细分析。 五、总结 从上面的分析,可知spring相关配置解析和组件创建其实是在web容器中,启动一个web应用的时候,即在其ServletContext组件创建的时候,首先解析web.xml获取该应用配置的listeners列表和servlet列表,然后保存在自身的一个属性中,然后通过分发生命周期事件ServletContextEvent给这些listeners,从而在listeners感知到应用在启动了,然后自定义自身的处理逻辑,如spring的ContextLoaderListener就是解析spring的配置文件并创建相关的bean,这样其实也是实现了一种代码的解耦;其次是创建配置的servlet列表,调用servlet的init方法,这样servlet可以自定义初始化逻辑,DispatcherServlet就是其中一个servlet。所以在ContextLoaderListener和DispatcherServlet的创建时,都会进行WebApplicationContext的创建,这里其实就是IOC容器的创建了,即会交给spring-context,spring-beans包相关的类进行处理了,故可以从这里作为一个入口,一层一层地剥spring的源码了。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。