1、时至今日我们认为Spring可能就是 解决方案、技术栈、全家桶
2、首当其冲的单纯就是Spring框架,做web开发又衍生出来了SpringMVC,后续为了能够更加快速的开发引入了SpringBoot,有了SpringBoot,我们可能基于SpringBoot要开发微服务,于是有了SpringCloud,
3、针对于Spring还有一些附属的框架
4、但是不管怎么样,今天整个spring的生态能做到这么大,都源自于spring框架自身的很多优秀特点,
当然另外一个SpringBoot给我们带来的好处是,内嵌了tomcat,内嵌的tomcat对于我们来讲,实际上是一个非常重要的特性,内嵌tomcat有两个特别大的好处
一个好处是 解决了SpringMVC中父子容器,在SpringBoot中没有人再提父子容器的问题了,这是在SpringMVC开发当中非常重要的一个问题,是需要我们大家解决的。
问问大家我们在SpirngMVC开发当中是怎么解决父子容器的问题的呢?能不能回答我,大家的回答太让我寒心了。
首先要明白的一个问题是,在SpringMVC开发中同时存在两个Spring工厂
springMVC的配置在web.xml当中我们会配置一个
DispatcherServlet
指定dispartcher.xml
DispatcherServlet其实就是spring的一个工厂
后续还会在web.xml中配置一个listener
ContextLoaderListener
ContextLoaderListener本质上也是创建了一个工厂
这样你在SpringMVC开发的过程中,实际上是有两个工厂,一个DispatcherServlet【child】一个ContextLoaderListener【root】,两个工厂并存
如果不经过任务处理的话,SpringMVC父子容器会带来一个问题,
Controller 去获取Service的时候,虽然Service 配置了事务,但是事务没有生效,原因,配置事务的时候是在父工厂配置的,而子工厂此时获得的是子工厂创建的service,这个问题的核心是,你在父工厂创建了service添加了事务
而在子工厂中 创建 了Service,但它没有事务 ,子工厂创建Controller 取的是子工厂的service,这个service是没有事务的。这是开发当中最常见的问题了,那么如何解决呢?
SpringBoot就没有父子容器问题,因为SpringBoot中的Tomcat是内嵌的,不需要外部集合的方式来解决,所以整个SpringBoot中是没有父子容器的。
第二个好处,一个tomcat是一个进程,而SpringBoot内嵌了Tomcat之后,我们就可以以jar包的形式,启动tomcat运行进程,这样就会产生一个特别有益的效果就是,在整个SpringBoot的开发过程当中,我们可以创建多个tomcat进程。换句话说,可以把一个大的应用 或者就是很多人说的 把单体应用,拆分成若干个独立的进程、独立的服务,都能对外发起请求接受相应。
所以这才是SpringBoot给我们带来的实质性内容,除了这些内容 其他的和SpringBoot没有任何关系。
正是因为有了SpringBoot能够让我们快速开发,同时内嵌一个Tomcat去运行多个进程,把一个单体应用进行拆分,所以才有了后续的SpringCloud,所以你要知道SpringCloud 为什么今天必须要嫁接SpringBoot,是因为SpringBoot有这些优势。
1、枯燥,从今天开始就要开始学习源码内容了,学习源码一定是枯燥的。
2、Mybatis的源码撑死算Spring的一个模块,Mybatis的代码看起来简单不复杂。
3、方方面面都要掌握,不管是那个细节都要掌握到位,到时候扣细节都是非常非常方便的。
4、整个Spring源码课程的安排【6-8次课搞定】
1、剖析源码围绕一个主题展开,就是Spring的工厂,但是也叫做容器,那好我想问问各位,为什么大家会把spring的工厂叫做容器呢?
作为整个spring 的工厂来讲,实际上工厂的责任是什么?工厂的责任是为了创建对象,但是创建完对象,他不仅仅是把这个对象创建起来,但同时他还得把这个对象存储在这个工厂当中,后续再给第二个调用者来使用。
2、比如说此时 有一个用户需要使用 User这个对象,工厂进行创建并存储,当第二个用户再来调用的时候就无需创建,直接使用就可以了。
3、能存储Order 能存储User 能存储一切它所创建的对象,那它不就是一个容器吗?当然会有一个前提,这些对象都得是单实例,因为我们当时讲spring的时候,它能创建单实例对象也能根据需要创建新的,如果是单实例的话指定为scope=singleton,如果是每次都创建新的需要指定为scope=prototype,工厂能存对象 存的是singleton对象,所以我们把工厂成为容器。
1、我们最常用的工厂是ApplicationContext 也叫应用上下文,这个工厂是Spring提供的较为高级的一个工厂,这个工厂复合了很多个功能,我们在编程的时候 用它最方便,但实际上它的角色都是被spring提供的其他工厂所分担了,ApplicationContext是我们编程过程中的一个门面,这就很类似于我们当时在讲Mybatis的时候,mybatis的门面是什么是SqlSession,用SqlSession来进行访问和操作,它给提供了很多方法,用起来比较方便,接口单一,但是实际上在实现的过程中,它是纷繁复杂的,而作为ApplicationContext这个工厂来讲,它也是spring编程当中的一个门面,它是一个很高级的东西,复合了很多其他类型 其他工厂的能力 集于一身,应用的时候使用高级工厂最方便,但是分析源码分析底层的时候 可不能使用ApplicationContext,功能太多了,分析它太乱了,那这个时候就得找到spring最为核心的底层工厂是BeanFactory
2、看一下相应的源码,是一个接口 后续通过实现类来进行使用,这里面的逻辑和当时我们将的ApplcationContext是完全一样的,ApplcationContext是工厂也是接口,一般会用ClassPathApplcationContext和BeanFactory是一样的。
BeanFactory2001年,两个Spring的作者,看注释写的很详细。
BeanFacotry严格遵循了类型单一职责的这个概念,所以这个工厂它演变成了一个非常复杂的体系,那么它这个体系是什么?
BeanFactory:Spring体系底层工厂,定义工厂的基本操作
HierarchicalBeanFactory:父子容器的管理
ConfigurableBeanFactory:
AutowireCapableBeanFactory:
ListableBeanFactory
DefaultListableBeanFactory
XMLBeanFactory
1、读取XML配置文件,所有的文本文件不可能每次用的时候 现用现读取,因为IO的效率非常差,往往会把这些文件 读取到内存当中,那当然读取到内存当中来到虚拟机,那就不能以字符串的形式来体现了,它应该要以对象的形式来存在,那势必就要把 XML配置文件 封装成Java对象
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
2、从工厂容器中获得对象
User user = (User) beanFactory.getBean("u");
1、在Spring源码中怎么读取xml?
2、Spring怎么把xml数据封装成java对象?
3、Spring如何封装了这些对象?
4、Spring封装完成对象之后如何根据需要去创建对象?
通过new ClassPathResource(“配置文件的路径”)
1、Spring如何读取XML配置文件?
new ClassPathResource("配置文件的路径")
2、那么ClassPathResource是什么东西呢?
ClassPathResource是Resource接口的实现类,这个实现类是通过类加载器的方式,来获取输入流。
ClassPathResource是Resource的一个子类,Resource接口的目的是什么?
3、Resource目的:读取相关资源文件的内容 获得输入流
- 1、文件 xml .properties .txt
- 2、网络中的资源
Resource继承了InputStreamSource,ClassPathResource实现了getInputStream根据类或者类加载器 获取输入流。要是其他类也是如此,这就是Spring对于IO的封装
我们在讲Mybatis的时候就说过,任何的一个框架在开发的过程当中都要对常用的功能进行封装,比如我们当时讲Mybatis的时候对反射进行了封装,今天讲的Spring就对IO进行了封装,对获取输入流进行了封装,ClassPathResource基于Resource完成的,基于ClassPathResource完成的。
FileSystemResource
ClassPathResource
ByteArrayResource
ServletContextResouce
通过这些的子实现类,完成对具体IO输入流的获取,把文件的内容读取到虚拟机中。
把xml对应的内容通过Resouce读取到JVM中
通过Resource的子实现类
以对象的形式来存在,参考Mybatis
mybatis-config.xml 用 Configuration来体现
mapper 用 MappedStatement来体现
spring中的这些对象被封装成了一个个BeanDefinition来体现的
BeanDefinition对应的就是xml中一个个的bean标签,
最后这些一个个的bean标签 都会被存在 JVM当中或者Spring当中
XML的解析,当时我们在讲Mybatis的时候说是通过Xpath的形式来解析。
spring的xml解析用的是SAX来解析的,把解析内容封装成了BeanDefine。