导航:首页 > 源码编译 > 最好的spring源码

最好的spring源码

发布时间:2024-01-21 07:57:26

A. 详解Spring mvc工作原理及源码分析

Model 模型层 (javaBean组件 = 领域模型(javaBean) + 业务层 + 持久层)

View 视图层( html、jsp…)

Controller 控制层(委托模型层进行数据处理)

springmvc是一个web层mvc框架,类似struts2。

springmvc是spring的部分,其实就是spring在原有基础上,又提供了web应用的mvc模块。

实现机制:

struts2是基于过滤器实现的。

springmvc是基于servlet实现的。

运行速度:

因为过滤器底层是servlet,所以springmvc的运行速度会稍微比structs2快。

struts2是多例的

springmvc单例的

参数封装:

struts2参数封装是基于属性进行封装。

springmvc是基于方法封装。颗粒度更细。

⑴ 用户发送请求至DispatcherServlet。

⑵ DispatcherServlet收到请求调用HandlerMapping查询具体的Handler。

⑶ HandlerMapping找到具体的处理器(具体配置的是哪个处理器的实现类),生成处理器对象及处理器拦截器(HandlerExcutorChain包含了Handler以及拦截器集合)返回给DispatcherServlet。

⑷ DispatcherServlet接收到HandlerMapping返回的HandlerExcutorChain后,调用HandlerAdapter请求执行具体的Handler(Controller)。

⑸ HandlerAdapter经过适配调用具体的Handler(Controller即后端控制器)。

⑹ Controller执行完成返回ModelAndView(其中包含逻辑视图和数据)给HandlerAdaptor。

⑺ HandlerAdaptor再将ModelAndView返回给DispatcherServlet。

⑻ DispatcherServlet请求视图解析器ViewReslover解析ModelAndView。

⑼ ViewReslover解析后返回具体View(物理视图)到DispatcherServlet。

⑽ DispatcherServlet请求渲染视图(即将模型数据填充至视图中) 根据View进行渲染视图。

⑾ 将渲染后的视图返回给DispatcherServlet。

⑿ DispatcherServlet将响应结果返回给用户。

(1)前端控制器DispatcherServlet(配置即可)

功能:中央处理器,接收请求,自己不做任何处理,而是将请求发送给其他组件进行处理。DispatcherServlet 是整个流程的控制中心。

(2)处理器映射器HandlerMapping(配置即可)

功能:根据DispatcherServlet发送的url请求路径查找Handler

常见的处理器映射器:BeanNameUrlHandlerMapping,SimpleUrlHandlerMapping,

,(不建议使用)

(3)处理器适配器HandlerAdapter(配置即可)

功能:按照特定规则(HandlerAdapter要求的规则)去执行Handler。

通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展多个适配器对更多类型的处理器进行执行。

常见的处理器适配器:HttpRequestHandlerAdapter,,

(4)处理器Handler即Controller(程序猿编写)

功能:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler。

(5)视图解析器ViewReslover(配置即可)

功能:进行视图解析,根据逻辑视图名解析成真正的视图。

ViewResolver负责将处理结果生成View视图,ViewResolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。

springmvc框架提供了多种View视图类型,如:jstlView、freemarkerView、pdfView...

(6)视图View(程序猿编写)

View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf...)

引入相关依赖:spring的基本包、springmvc需要的spring-webmvc,日志相关的slf4j-log4j12,jsp相关的jstl、servlet-api、jsp-api。

因为DispatcherServlet本身就是一个Servlet,所以需要在web.xml配置。

一、使用默认加载springmvc配置文件的方式,必须按照以下规范:

①命名规则:-servlet.xml ====> springmvc-servlet.xml

②路径规则:-servlet.xml必须放在WEB-INF下边

二、如果要不按照默认加载位置,则需要在web.xml中通过标签来指定springmvc配置文件的加载路径,如上图所示。

将自定义的 Controller 处理器配置到 spring 容器中交由 spring 容器来管理,因为这里的 springmvc.xml 配置文件中处理器映射器配置的是 BeanNameUrlHandlerMapping ,根据名字可知这个处理器映射器是根据 bean (自定义Controller) 的 name 属性值url去寻找执行类 Handler(Controller) , 所以bean的name属性值即是要和用户发送的请求路径匹配的 url 。

根据视图解析路径:WEB-INF/jsps/index.jsp

功能:根据bean(自定义Controller)的name属性的url去寻找执行类Controller。

功能:自定义的处理器(Controller)实现了Controller接口时,适配器就会执行Controller的具体方法。

会自动判断自定义的处理器(Controller)是否实现了Controller接口,如果是,它将会自动调用处理器的handleRequest方法。

Controller接口中有一个方法叫handleRequest,也就是处理器方法。

因此,自定义的Controller要想被调用就必须实现Controller接口,重写Controller接口中的处理器方法。

B. SpringBoot内置生命周期事件详解 SpringBoot源码(十)

SpringBoot中文注释项目Github地址:扒派族

https://github.com/yuanmabiji/spring-boot-2.1.0.RELEASE

本篇接 SpringBoot事件监听机制源码分析(上) SpringBoot源码(九)

温故而知新,我们来简单回顾一下上篇的内容,上一篇我们分析了 SpringBoot启动时广播生命周期事件的原理羡汪 ,现将关键步骤再浓缩总结下:

上篇文章的侧重点是分析了SpringBoot启动时广播生命周期事件的原理,此篇文章我们再来详细分析SpringBoot内置的7种生命周期事件的源码。

分析SpringBoot的生命周期事件,我们先来看一张类结构图:

由上图可以看到事件类之间的关系:

EventObject 类是JDK的事件基类,可以说是所有Java事件类的基本,即所有的Java事件类都直接或间接继承于该类,源码如下:

可以看到 EventObject 类只有一个属性 source ,这个属性是用来记录最初事件是发生在哪个类,举个栗子,比如在SpringBoot启动过程中会发射 ApplicationStartingEvent 事件,而这个事件最初是在 SpringApplication 类中发射的,因此 source 就是 SpringApplication 对象。

ApplicationEvent 继承了DK的事件基类 EventObject 类,是Spring的事件基类,被所有Spring的具体事件类继承,源码如下:

可以看到 ApplicationEvent 有且仅有一个属性 timestamp ,该属性是用来记录事件发生的时间。

SpringApplicationEvent 类继承了Spring的事件基类 ApplicationEvent ,是所有SpringBoot内置生命周期事件的父类,源码如下:

可以看到 SpringApplicationEvent 有且仅有一个属性 args ,该属性就是SpringBoot启动时的命令行参数即标注 @SpringBootApplication 启动类中 main 函数的参数。

接下来我们再来看一下 SpringBoot 内置生命周期事件即 SpringApplicationEvent 的具体子类们。

SpringBoot开始启动时便会发布 ApplicationStartingEvent 事件,其发布时机在环境变量Environment或容器ApplicationContext创建前但在注册 ApplicationListener 具体监听器之后,标志标志 SpringApplication 开始启动。

可以看到 事件多了一个 environment 属性,我们不妨想一下,多了 environment 属性的作用是啥?
答案就是 事件的 environment 属性作用是利用事件发布订阅机制,相应监听器们可以从 事件中取出 environment 变量,然后我们可以为 environment 属性增加属性值或读出 environment 变量中的值。

当SpringApplication已经开始启动且环境变量 Environment 已经创建后,并且为环境变量 Environment 配置了命令行和 Servlet 等类型的环春弊境变量后,此时会发布 事件。

监听 事件的第一个监听器是 ConfigFileApplicationListener ,因为是 ConfigFileApplicationListener 监听器还要为环境变量 Environment 增加 application.properties 配置文件中的环境变量;此后还有一些也是监听 事件的其他监听器监听到此事件时,此时可以说环境变量 Environment 几乎已经完全准备好了。

可以看到 事件多了个 类型的 context 属性, context 属性的作用同样是为了相应监听器可以拿到这个 context 属性执行一些逻辑,具体作用将在 3.4.4 详述。

事件在 ApplicationContext 容器创建后,且为 ApplicationContext 容器设置了 environment 变量和执行了 的初始化方法后但在bean定义加载前触发,标志ApplicationContext已经初始化完毕。

同样可以看到 ApplicationPreparedEvent 事件多了个 类型的 context 属性,多了 context 属性的作用是能让监听该事件的监听器们能拿到 context 属性,监听器拿到 context 属性一般有如下作用:

ApplicationPreparedEvent 事件在 ApplicationContext 容器已经完全准备好时但在容器刷新前触发,在这个阶段 bean 定义已经加载完毕还有 environment 已经准备好可以用了。

ApplicationStartedEvent 事件将在容器刷新后但 ApplicationRunner 和 CommandLineRunner 的 run 方法执行前触发,标志 Spring 容器已经刷新,此时容器已经准备完毕了。

ApplicationReadyEvent 事件在调用完 ApplicationRunner 和 CommandLineRunner 的 run 方法后触发,此时标志 SpringApplication 已经正在运行。

可以看到 ApplicationFailedEvent 事件除了多了一个 context 属性外,还多了一个 Throwable 类型的 exception 属性用来记录SpringBoot启动失败时的异常。

ApplicationFailedEvent 事件在SpringBoot启动失败时触发,标志SpringBoot启动失败。

此篇文章相对简单,对SpringBoot内置的7种生命周期事件进行了详细分析。我们还是引用上篇文章的一张图来回顾一下这些生命周期事件及其用途:

由于有一些小伙伴们建议之前有些源码分析文章太长,导致耐心不够,看不下去,因此,之后的源码分析文章如果太长的话,笔者将会考虑拆分为几篇文章,这样就比较短小了,比较容易看完,嘿嘿。

【源码笔记】Github地址:

https://github.com/yuanmabiji/Java-SourceCode-Blogs

点赞搞起来,嘿嘿嘿!

公众号【 源码笔记 】专注于Java后端系列框架的源码分析。

C. 阿里内部都在用的Spring源码手册,学会也是阿里人

最近在使用Spring MVC过程中遇到了一些问题,网上搜索不少帖子后虽然找到了答案和解决方法,但这些答案大部分都只是给了结论,并没有说明具体原因,感觉总是有点不太满意。

更重要的是这些所谓的结论大多是抄来抄去,基本源自一家,真实性也有待考证。

那作为程序员怎么能知其所以然呢?

此处请大家内心默读三遍。

阅读源码的魅力在于:

分享一本阿里内部人都在使用的Spring源码手册分享给读者朋友们,学会掌握了本手册内容,距离成为阿里人也是成功的跨了一大步子。

第一部分:核心实现原理

第二部分:企业应用

D. Spring事件监听机制源码解析

1.Spring事件监听体系包括三个组件:事件、事件监听器搜哪,事件广播器。

事件:定义事件类型和事件源,需要继承ApplicationEvent。

事件监听器:用来监听某一类的事件,并且执行具体业务逻辑,需要实现ApplicationListener 接口或者需要用@ListenerEvent(T)注解。好比观察者模式中的观察者。

事件多播器:负责广播通知所有监听器,所有的事件监听判猛器都注册在了事件多播器中。好比观察者模式中的被观察者。Spring容器默认生成的是同步事件多播器。可以自定义事件多播器,定义为异步方式。

创建 的过程中,会执行refresh()中的()方法。该方法先获取bean工厂,然后判断工厂是否包含了beanName 为 applicationEventMulticaster的bean。如果包含了,则获取该bean,赋值给applicationEventMulticaster 属性。如果没有,则创建一个 对象,并且赋值给 applicationEventMulticaster 。实现了源码如下:

监听器的注册有两种,通过实现 ApplicationListener接口或者添加@EventListener注解。

注册的逻辑实现在refresh()中的registerListeners()方法里面。第一步,先获取当前ApplicationContext中已经添加的 applicationListeners(SpringMVC源码中有用到),遍历添加到多播器中。第二步,获取实现了ApplicationListener接口的listenerBeanNames集合,添加至多掘漏桥播器中。第三步,判断是否有早期事件,如果有则发起广播。

思考一下,上面的代码中第二步为啥添加的是listenerBeanName?

如果监听器是懒加载的话(即有@Lazy 注解)。那么在这个时候创建监听器显然是不对的,这个时候不能创建监听器。所以添加监听器到多播器的具体逻辑放在初始化具体的监听器之后。通过 BeanPostProcessor 的接口实现。具体的实现类是 ApplicationListenerDetector 。这个类是在 refreah()中prepareBeanFactory()方法中添加的。代码如下:

在创建 的构造方法中,会执行org.springframework.context.annotation.AnnotationConfigUtils#(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object) 方法。这个方法中会添加两个 beanDefs, 代码如下:

EventListenerMethodProcessor:事件监听器的BeanFactory后置处理器,在前期会创建 DefaultEventListenerFactory ,后期在创建好Bean之后,根据 EventListener 属性,调用DefaultEventListenerFactory创建具体的 。

DefaultEventListenerFactory:监听器的创建工厂,用来创建 。

EventListenerMethodProcessor 的类继承图如下:

在refreash的()中会调用 org.springframework.context.event.EventListenerMethodProcessor#postProcessBeanFactory方法,获取EventListenerFactory 类型的 Bean。代码如下:

在 org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons 方法中,创建完所有的单例Bean 之后,会遍历所有Bean是否实现了 SmartInitializingSingleton 接口。如果实现接口会执行该 Bean 的 afterSingletonsInstantiated() 方法。代码如下:

org.springframework.context.event.EventListenerMethodProcessor#afterSingletonsInstantiated 中会调用私有方法 processBean()进行 ApplicationEventAdatper 的创建。代码如下:

可以通过调用 org.springframework.context.support.AbstractApplicationContext#publishEvent(java.lang.Object, org.springframework.core.ResolvableType) 方法进行事件的调用。代码如下:

中的 multicasEvent,invokeListener,doInvokeListener 三个方法代码如下:

SpringMVC中就是通过Spring的事件机制进行九大组件的初始化。

监听器定义在FrameworkServlet类中,作为内部类。代码如下:

监听器的添加在org.springframework.web.servlet.FrameworkServlet# 中进行。通过SourceFilteringListener进行包装。添加代码如下:

在refresh中的registerListeners方法进行添加,代码如下:

在refresh中的finishRefresh()方法中,会调用publishEvnet(new ContextRefreshedEvent(this))发布事件。进行多播器广播,代码如下

最终会调到FrameworkServlet.this.onApplicationEvent(event)。

E. Spring源码解析哪本书好

解析的步骤: 1、加载web.xml、加载监听器<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 2、ContextLoaderListener 初始化initWebApplicationContext方法创建 org.springframework.web.context.support. XmlWebApplicationContext对象 3、XmlWebApplicationContext调用loadBeanDefinitions方法,该方法主要做两件事情:初始化XmlBeanDefinitionReader、获取applicationContext.xml配置文件的路径、然后把事情交给XmlBeanDefinitionReader来处理 4、XmlBeanDefinitionReader获取到applicationContext.xml配置文件的路径、读取配置文件的内容得到一个输入流、对输入流转码操作、然后封装成一个inputSource对象、再然后封装成一个document对象;在生成document对象的同事也生成了一个Resource对象、这两个对象分部是:document对象承载配置文件的主要内容信息、Resource承载配置文件的描述信息以及一些验证信息。 再由Resource对象创建一个XmlReaderContext。完成了以上操作XmlBeanDefinitionReader就把document对象和XmlReaderContext对象交给来处理 5、1)、对XmlReaderContext装饰成一个BeanDefinitionParserDelegate对象; 2)、迭代document对象、把document对象拆分成Element元素逐个逐个解析; 3)、使用BeanDefinitionParserDelegate装饰对象解析Element元素或者说标签。 if (absoluteLocation) { try { int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources); if (logger.isDebugEnabled()) { logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]"); } } catch (BeanDefinitionStoreException ex) { getReaderContext().error( "Failed to import bean definitions from URL location [" + location + "]", ele, ex); } } else { // No URL -> considering resource location as relative to the current file. try { int importCount; Resource relativeResource = getReaderContext().getResource().createRelative(location); if (relativeResource.exists()) { importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource); actualResources.add(relativeResource); } else { String baseLocation = getReaderContext().getResource().getURL().toString(); importCount = getReaderContext().getReader().loadBeanDefinitions( StringUtils.applyRelativePath(baseLocation, location), actualResources); } if (logger.isDebugEnabled()) { logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]"); } } catch (IOException ex) { getReaderContext().error("Failed to resolve current resource location", ele, ex); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]", ele, ex); } } Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]); getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele)); } 解析alias标签的方法:

F. Spring源码解析(一)- 容器的基本实现

       Spring使用 基本的JavaBean 来完成以前只可能由EJB完成的事情,是个分层架构。Spring创建bean都需要通过 读取 、 解析 、 校验配置文件, 然后注册创建成Bean。 Spring是一个Bean容器 , 主要作用是替我们管理bean对象 (简单的Java类对象的生命周期)。不管框架如何强大,还是需要我们程序员来告诉其一些必要信息的(比如要 管理的bean对象的类相关信息、是否开启组件扫档纳描 等),这些我们称之为对 Spring框架的配置 ,目前主流的配置方式是 通过使用配置文件或注解。

        Spring中最核心的两个源雀类: DefaultListableBeanFactory、XmlBeanDifinitionReader。DefaultListableBeanFactory 是整个bean加载的核心部分,是Spring注册及加载bean的默认实现 。XmlBeanDefinitionReader 主要使用reader属性对资源文件进行读取和注册。

        XML配置文件读取是Spring中重要的功能,大部分Spring大部分功能都是 以配置作为切入点 。 XmlBeanFactory 继承自 DefaultListableBeanFactory ,而对于 DefaultListableBeanFactory 不同的地方其实是在 XmlBeanFactory 中使用了自定义的XML读取器 XmlBeanDefinitionReader ,主要用于从XML文档中读取 BeanDefinition, 实现了个性化的 BeanDefinitionReader 读取, DefaultListableBeanFactory 继承了 并实现了 以及 BeanDefinitionRegistry 接口。

        Spring的配置文件读取是通过ClasaPathResource进行封装的 ,如:new ClassPathResource("bean.xml")。在java中, 将不同来源的资源的读取逻辑抽象成URL ,通过注册不同的 handler来处理。 一般handler的类型使用不同的前缀,URL没有默认定义相对的path路径,也 没有提供相关方法对资源进行检查 ,顾Spring对其内部需要使用到的资源做了属于自己的抽象结构, 用Resource接口来封装底层资源。

        Resource 接口继承 InputStreamSource(封装了任何能返回InputStream的类)。

        Resource接口抽象了所有Spring内部使用到的底层资源 ,首先它定义了3个能判断当前资源状态的方法: 存在性(exists)、可读性(isReadable)、是否处于打开状态(isOpen) 。有了Resource接口便可以对所有资源进行统一处理。 ClassPathResource 中的实现是通过class或 classLoader 提供的底层方法进行调用。以此完成对配置文件资源的封装。

        当通过Resource相关类完成了对配置文件进行封装,接下来由 XmlBeanDefinitionReader 完成对配置文件的读取工作。雹蠢早

       XML文件的验证模式有两种:DTD、XSD(XML Schema).

        DTD即文档类型定义, 是一种XML约束模式语言,是XML文件的验证机制 。是一种保证XML文档格式正确的有效方法, 可以通过比较XML文档和DTD文件来查看文档是否符合规范,元素和标签的使用是否正确 。一个DTD文档包含:元素的定义规则、元素间关系的定义规则、元素可使用的属性、可使用的实体或符号规则。 要使用DTD验证模式需要在XML文件的头部声明。

        XML Schema语言就是XSD。   XML Schema描述了XML文档的结构。可以用一个指定的XML Schema来验证某个XML文档,以检查该XML文档是否符合其要求。也可以 通过XML Schema指定一个XML文档所允许的结构和内容 。XML Schema本身也是一个XML文档,符合XML语法结构,可以用通用的XML解析器解析它。    

        使用XML Schema文档对XML实例进行校验,要声明名称空间和指定该名称空间所对应的XML Schema文档存储位置 。通过schemaLocation属性来指定名称空间所对应的XML Schema文档的存储地址(1、名称空间URL;2、该名称空间所标识的XML Schema文件地址或URL地址)。

      另外验证模式通过 XmlBeanDefinitionReader 中的setValidationMode方法进行设定。而 Spring 用来检测验证模式的方法实际上就是判断是否包含 DOCTYPE ,如果包含就是 DTD ,否则就是 XSD 。

        XML文件经过验证模式,交由DocumentLoader进行解析成对应的 Document。 而解析的过程中存在这么一环节:(EntityResolver) 根据声明去寻找对应的DTD定义,以便对文档进行验证认证 。也可以通过setEntityResolver设置DTD定义。EntityResolver它用来接收两个参数publicId和systemId,xsd格式文件通常publicId为null。而对于不同的验证模式采用不同的解析器进行解析,并把文件转换成Document文件,用于提取及注册bean。

          Document 文件通过 BeanDefinitionDocumentReader 进行内部逻辑处理,并提取root用于作为参数继续完成BeanDefinition的注册。

阅读全文

与最好的spring源码相关的资料

热点内容
汉语词典pdf下载 浏览:351
android公网ip 浏览:611
要塞1地图放哪个文件夹 浏览:848
凡科建站怎么弄服务器 浏览:939
苹果手机怎么设置app播放 浏览:202
下载网站源码用什么浏览器 浏览:241
六线谱pdf 浏览:156
linuxmysqlsock 浏览:239
人教版数学pdf下载 浏览:460
文档安全加密系统 浏览:491
数控铣床编程简单数字 浏览:788
编程电缆如何重启 浏览:121
myqq命令行发消息 浏览:365
日产逍客怎么使用app升窗 浏览:503
安卓系统怎么快速删除微信内容 浏览:653
csharppython 浏览:409
程序员脖子按摩仪 浏览:563
小米桌面文件夹乱码怎么回事 浏览:858
点歌台app怎么连接 浏览:318
大学电脑编程学什么好 浏览:348