JavaEE的渊源
- [1. JavaEE的起源](#1. JavaEE的起源)
- [2. JavaEE与Spring的诞生](#2. JavaEE与Spring的诞生)
- [3. JavaEE发展历程(2003-2007)](#3. JavaEE发展历程(2003-2007))
- [4. JavaEE发展历程(2009-至今)](#4. JavaEE发展历程(2009-至今))
- [5. Java的Spec数目与网络结构](#5. Java的Spec数目与网络结构)
1. JavaEE的起源
我们首先来讲一下JavaEE的起源 ,为什么要来讲起源 ?
💻因为JavaEE其实是一个现象级的事件。
💻我们知道同时期,其实在后端的开发,是有很多的竞品的。比如说Java开发平台 ,.Net的开发平台 ,还有曾经昙花一现的什么Perl和PHP ,还有现在的go,这些都能用来开发后端。
💻但唯独JavaEE是持续时间最长,最成熟,产品最多,选择性最多,从业人员也是最多的一个开发平台。
但是为什么会形成这样一个现象?
💻其实这一切在JavaEE,Java一开始出现的时候,30年前就已经决定了。
它走了跟其它的东西完全不同的一条道路,它建立的不是一个产品或者是一种语言,Java建立的是一个生态一个市场,让很多的企业能参与到生态里头来,在市场上竞争,从而形成百花齐放,优胜劣汰,这样才会使得Java的市场,慢慢的一步一步的发展到今天,成为占比最大的一个后端的开发市场。以生态市场来说,没有任何一个后端的开发生态市场,比Java更加的成熟。
Java其实曾经有三个版本------JavaSE、JavaEE、JavaME。
- JavaSE:标准版
- JavaEE:企业版
- JavaME:移动版
💻就是我们最熟悉的JavaSE ,这是Java最基本的语言版本,每一个版本中间增加不同的特性。
💻在JavaSE的基础上头,为了开发服务器端的应用 ,或者我们称之为企业级的应用,它有JavaEE ,JavaEE其实不是一个产品,它是一系列的规范,我们后面会讲从一开始它就是一个规范,而不是像Java那样的是一个产品,这个规范其实包含了,开发后端应用的,所有所需要的技术,当然它不是一开始就这么大的,是随着后端的开发的技术不断的发展,JavaEE的规范也在不断的扩充和修改,从而形成了今天庞大的JavaEE的这样一个规范。
💻它还有一个是它试图占领移动端,但是这个是不成功的,我们知道移动端今天基本上是,安卓和ios的天下,ios就是封闭系统,跟Java没关系是吧,安卓还是基于Java的,但是它不是基于JavaME的,而是就是基于Java的这样的一个结构。
💻在JavaME 的移动版来说,今天已经销声匿迹了,今天我们所能看到的,主要也就是JavaSE和JavaEE,JavaSE的每一个新版本的发布,也紧跟着会有一个新的JavaEE的发布,因为它会用到JavaSE中间的,一些新特性,从而产生一个新版本的JavaEE基本上是这样的一个特征。
我们从最开始的起源开始,JavaEE起源于99年,当时的Sun公司,大家知道Java是Sun公司的,但是Sun公司倒闭了,Sun公司被Oracle公司收购了,所以现在是Oracle公司的Java。
💻Sun公司提出了一个新的成员,就是它要在企业级应用上头去定一个规范,这个规范是什么规范,企业级的应用要以容器和组件的方式,来提供服务的。
💻我们知道之前我们写,程序的时候你是写个程序,这个程序放到机器上运行就好了。
💻但对于企业级的这个东西来说,其实它要管的事情太多了,它要管网络通讯,要管安全,要管多线程并发等等这些事情。
所以你要在企业级的应用,环境中间去写一个程序,你要把这事情都管了,其实是挺困难的。
💻Sun公司当时提出的想法就是,把一些共性的东西,用容器去管,个性化的东西比如说每个,企业自己的业务由组件去管,然后容器和组件一起构成我们最终的企业级的服务,来提供我们企业级的应用,这是它的最基本的想法 :
就是把企业级的后端应用,把它分成了容器和组件,容器管共性的东西,组件管个性化企业的这些业务需求,为了让这个东西能形成一个生态,它定义了一系列的规范,就是容器该怎么做,做什么组件该怎么做做什么,容器和组件之间该怎样连接到一起,它定义了一系列的规范,把这个规范称之为JavaEE的规范。
💻所以JavaEE从一开始出现,它不是首先出现了一个产品,而是出现了一个设计,这个设计就是服务器端的应用,是分为容器和组件的,然后容器有一系列的规范,组件有一系列的规范,只要你符合规范的组件和容器,就能够合起来构成我们企业的应用,这就是最开始出现的J2EE的概念。
💻💻💻容器和组件,其实所面对的这个人群是不一样的。
容器所面对的其实是开发商,很多的开发商都可以,按照JavaEE的规范,去开发各种各样的容器。
比如大家所熟悉的,Tomcat就是一个容器,同样符合规范的容器,还有很多比如说Jetty,也是符合JavaEE的容器。
💻对于开发者来 说,你开发的程序是组件 ,我开发的程序是在Tomcat容器里去跑的,因为Tomcat容器,和Jetty容器都符合容器的规范,所以我开发的组件,是既可以在Tomcat跑,也可以在Jetty中间跑,这就使得这不是一个单一产品的市场,而是它定义的一个规范,在每一个规范下面,都是有很多的产品可以做出来,然后这些产品可以竞争,然后从而优胜劣汰,最后整个市场会往前发展,这就是JavaEE的最开始的这样的一个思路。
总结 :
从99年的12月份开始,出现了第一个版本的,JavaEE的这样的一个规范,这样的一个规范把后端的,服务分成了容器和组件,定义了一个清晰的架构和全景,明确了说组件应该做什么,容器应该做什么,而且对于Sun公司来说,它并不是说这个容器只能由Sun公司来做,这个容器它可以把规范公开了以后,可以让所有的厂商只要你有兴趣,就来做这样的一个容器。
2. JavaEE与Spring的诞生
💻我们来看一下在99年12月份的,第一版的JavaEE,那时候叫做J2EE的,结构是什么样的?
它的结构是这样的。
💻它的容器分成两种容器,一种叫做Web容器,一种叫做EJB容器,为什么分成两种容器?
💻它跟当时的技术是有一定的关系的,当时我们在做企业级应用的时候,主要是两种架构,一种是B/S的架构 一种是C/S的架构。
- B/S的架构叫什么,叫做浏览器Browser/Server的架构,就是基于网页的浏览器这样的一个架构;
- C/S的架构是什么,是Client/Server,架构就是前端是一个应用程序,后端是这个服务器这样的一个架构。
💻它分成两个容器,主要是针对于B/S架构,因为当时99年那个时候,上网还是很奢侈的事情,但是从技术界来说,已经认识到说,B/S的架构,会成为未来的主流
💻所以它在做JavaEE的架构的时候,你可以看到它就考虑的是B/S的架构,对于B/S的架构它有一个问题,就是服务器往前端丢的是什么呢,是HTML,是吧,浏览器看到是HTML,所有的界面和结果,都是用HTML来呈现的,因为我们是一个应用程序,而不是一个死页面,这个HTML会根据你的业务逻辑,HTML的内容,和你的业务逻辑不断的变化,所以HTML的产生是动态的,而不是静态的不是一个死文件,你填的内容,包括长什么样子,都其实根据你的业务逻辑,在不断的变,这个HTML势必是由服务器产生的,因为逻辑在服务器上是吧,而不是在前端,在浏览器里头,是肯定是没有逻辑的,逻辑在服务器上,所以只能由服务器,根据业务逻辑算出来的结果,来渲染形成HTML,然后送给前端,前端其实很简单就是拿到,HTML把它展现出来就好了,这是当时的这样的一个架构。
💻所以它把服务器里头就分成了两个容器,一个容器负责渲染生成HTML,一个容器负责去做业务逻辑。
这么做的主要的原因,它因为我们在体系结构中间,有一个MVC的,这样的一个分层的架构,在面向对象中间会讲,它其实就是基于这样的一个思想,MVC的分层的架构提出的一个J2EE,的最初的体系结构,前面的Web Container,就是其中的V叫做View层,EJB的Container,就是后面的模型层Model,用来负责做业务逻辑。
💻但是在技术架构上面,你可以看到,这两个容器的规范里头,是有很多相同的地方,当然也有不同的地方,下面这一部分都是相同的,它都支持比如说JDBC,大家应该知道JDBC,就是J2EE中间的,最早就存在的一个规范,访问数据库的规范,不同的数据库厂商,会按照J2EE的JDBC的规范,去开发JDBC的,我们叫做Driver JDBC的驱动程序,只要你符合JDBC的规范,我们在上面写代码的时候,其实都是基于JDBC去访问的,而不是基于关于数据库的厂商的逻辑去做的,那个规格去做的,所以JDBC是大家熟悉的,这就是个J2EE的规范。
💻支持这个事务的规范就是JTA,支持这个消息驱动的规范JMS,支持如何发邮件的规范Java Mail,以及说它中间有一个相互互联的规范,叫做RMI-IIOP,这是Web Container,和EJB Container的之间相互通讯。
💻因为Web Container的负责产生页面,EJB Container负责做逻辑,所以它之间要相互调用,会产生这一切的规范,这些规范都是一样的,不同的地方在于说,在Web Container中间,主要是用Servlet和JSP,来形成渲染的HTML,而在EJB的Container中间,是靠的EJB,来实现我们的业务逻辑,就是用EJB的Bean来实现我们的业务逻辑。
💻我们可以看到它分成两个容器以后,Web Container主要负责HTML的渲染,而EJB这个容器主要负责业务逻辑,然后它们之间是可以相互访问的,访问的方式是通过我们在中间看到的,RMI-IIOP规范,来实现相互的访问。
💻对于这两个容器来说,它都通过JDBC可以去访问数据库,所以从技术上来说,你在Web Container中间,也可以通过JDBC去访问数据库,也可以在EJB中间,通过JDBC去访问数据库,不过它推荐的做法来说,是Web Container只负责HTML的渲染,而EJB的容器负责业务逻辑,去访问数据库之类的。
💻对于前端来说,我们刚才说到,它分为B/S的前端,和C/S的前端,C/S前端就是基于JavaSE的,在JavaSE上头,你依然可以使用JDBC的规范。
就是JDBC的规范不一定是要用到容器里的,容器当然支持JDBC的规范,可以为容器的组件,提供JDBC之类的这些东西,但是大多数JavaEE的规范,都可以直接在JavaSE的用,只不过是说这时候并没有一个容器的存在,而你需要自己去把这些,比如JDBC的驱动,这些东西自己Load起来。如果是在服务器端在容器里头,你其实根本不用去管这些东西,是怎样被Load起来的,它的管理都是由容器去负责管理的,但是在前端虽然没有容器,但是你可以直接去使用。
💻Java在最开始的时候支持,在HTML中间插入一个Applet,去运行Java的程序,因为最开始的HTML,是不具备任何逻辑功能的,是纯粹就是用来显示界面的,当然我们在前端会有很多的,比如说动态的要求,那个时候还没有JavaScript,所以Java在那个时候,提供了一个Applet的,这样的一个小插件,插在前面的浏览器里头,可以运行Java程序,从而具备Java程序所提供的一些动态的特性,包括去访问后端的东西等等这些特性,当然这个东西死亡了,死亡的原因是因为后来出现了------JavaScript,那个东西就不依赖于任何东西,由浏览器原生的支持JavaScript去运行,所以它的性能和效率,它的效率会比通过 Applet的去进行,Java程序的效率会更高,但是作为历史我们知道,它的沿革是这么来的,这是最早的版本。
总结:
第一个版本的J2EE的规范,规范里头就已经出现了,我们所说的,两个非常核心的概念,服务器端的部分是由容器和组件构成的 。
容器是由厂商提供的,按照规范可以提供各种各样的容器,只要这些容器是符合J2EE规范的,你按照这个规范所写的组件,就能在这个容器里去跑,所以这样的组件和容器的体系结构的划分,以及用技术规范去规范容器和组件的开发,创造了一直到今天为止,依然非常繁荣的,JavaEE的这个生态链的存在,这是最早的版本。
- 2001年的3月份,J2EE1.3增加的主要是什么,增加的就是XML。
💻基本上就跟着当时技术的潮流,在1999年时候,XML其实还并不是大家,广泛接受的一个东西,服务器服务器之间的调用,还是通过一些二进制的协议,比如说RMI-IIOP来做的,所以在2001年3月份的,1.3版本中间,它主要修改的就是RMI-IIOP,这是它最大的一个改进。
💻全部改成了基于XML的这样一种通讯的方式,所以它也衍生了XML的,一系列的这些规范,比如说怎么去读写XML,同时在这个时代,JavaEE出现了以后,订立了容器和组件的这样一个结构,订立了规范去发展。
- 在2002年10月份,Rod Johnson出了一本书叫做,《expert one to one J2EE Development without EJB》。
它这本书的中心的想法是什么,它觉得在这个结构里头你可以看到,它在服务器端分成了Web Container和EJB Container两个容器,其实在EJB Container中间能做的事情,在Web Container中间也全部可以做,它在提出一个问题,为什么需要EJB Container,我们不要这个EJB Container,就依靠这个Web Container是否能,开发出一个应用出来,所以它以这样的一个想法写了这么一本书。
《J2EE Development without EJB》里头配了一个实例,这个实例就是不用后面的EJB Container,它完整的开发出了一个在线的订座系统,为了开发在线订座系统,它使用了大量的面向对象的设计的方法,设计了一个底层的框架,这个框架里头第一次支持了两个东西!!!!!🐂🐂🐂
💻一个叫做依赖注入,一个叫做AOP,这两个东西当时在J2EE中间都是没有的,就在J2EE规范中间,没有关于IOC的定义,和AOP的定义。
至于什么是IoC什么是AOP,一两句话讲不清楚,我们在之后的课中间再讲,因为这是Spring框架,两个最核心的思想,一开始就出现了这个思想,而这两个思想,又跟面向对象的设计息息相关,也就是我们要完整的讲完,面向对象的设计以后,你才会知道IoC起什么作用,AOP起什么作用然后再,到Spring框架中间去看,说Spring框架,是怎样来实现IoC和AOP的。
💻在书中,他展示了如何在不使用EJB的情况下构建高质量,可扩展的在线座位预定程序。为了构建这个程序,他编写了超过30000行的基础结构代码(牛逼)!《Expert One-on-One J2EE设计和开发》一炮走红。
它不仅仅是一个订座系统,它是基于 JavaEE的Web Container的规范,然后加上了,在J2EE的规范中间,没有的IoC的特性和AOP的特性,形成了一个在线订座系统,这本书的出版,其实让当时大家觉得眼光一亮,因为J2EE的规范,这时候已经相对来说有二三十条规范了,所以在J2EE上去开发东西,会相对比较繁琐比较累,而这本书的出现,其实给大家开了一条新的路子,就是我们可以不要J2EE的整套东西,我只选择其中的一小部分东西,甚至很少的一部分东西,我就能开发出一个系统来,虽然这个系统可能在某些方面,不如在重量级的,J2EE的结构上的,开发出来的系统那么强大,但是这个系统,它其实有它自己的这样的一个特点,这本书出版了以后其实,已经起了很大的反响。
它是在02年10月份出版的,其中在2003年的1月份,Yann Caroff这个人,在那本书下面写了一个书评,说这本书里头所写的内容是令人激动的,它创造了一个新的时代很长,大概中心的意思是这样的意思,为什么要把他的书评拿出来。
💻因为2003年的2月份,Juergen Hoeller和Yann Caroff这两个人,找到了Rod Johnson,跟他说你这个东西做得太有意思了,我们把这本书里头的,一部分代码把它拿出来,做成一个独立的框架,这个框架的名字就叫做Spring,这个名字就是Yann Caroff起的这个名字。------Spring的诞生
寓意着要给处于"冬天"的传统J2EE带来新开始。
Rod Johnson的书以非常详尽,翔实和实用的方式介绍了J2EE的最佳实践。从编码标准,陈规,bean实体,单元测试,设计决策,持久性,缓存,EJB,model-2表示层,视图,验证技术还有性能等方面都有翔实的论述。书中案例是带领大家做个java项目开发的绝佳之旅,从开发现状、制约因子,风险及至最佳决策。它不光是一本教科书,还是一个Java开发的知识库。
- 2003年6月,Spring 0.9以Apache 2.0许可协议发布。
- 2004年3月Spring 1.0版发布。实际上在1.0发布之前,Spring就已经得到开发人员的广泛使用。
- 2004年8月,Rod Johnson,Juergen Hoeller,Keith Donald和Colin Sampaleanu共同创立了interface21,一家专注于Spring咨询,培训和支持的公司。
Yann Caroff在不久就离开了团队。 Rod Johnson也在2012年离开了Spring团队。Juergen Hoeller则一直是Spring的活跃的开发者。
3. JavaEE发展历程(2003-2007)
💻三个人就开始着手来写这个框架,与此同时J2EE的框架推出了1.4版本,也就是在2003年的11月份,推出了1.4版本。在这个版本中间,它其实首次加入了Web Service,这也是Web Service第一次出现,在J2EE的框架中间,大家知道2003年是,互联网刚刚出现的年代,第一次互联网的浪潮破灭了,然后开始复兴的这个年代,那个时候Web的网页大家还没有玩溜,J2EE的标准里头,已经开始出现了Web Service,也就是我们现在的Web服务的,这样的一些相关的规范,只有这些规范出现以后,才会有不同的厂商上面,去开发出相应的产品,然后大家在这部分上去用这个产品才发现,这个东西有什么样的好处才会往后发展,所以这是在2003年11月份的事情,其实它们没有发现,它的最大的竞争对手已经产生了。
💻也就是在2004年3月份,一年的时间内,三个人开发出了一个框架叫做,Spring1.0版本发布,Spring的框架与J2EE的框架最大的区分在于什么!!!
- 它没有EJB,它只遵循了J2EE的Web Container的,这部分的规范,除了这个以外它还加入了,它两大核心的特性。(这是在J2EE中间没有的,就是AOP和IoC)
💻因为AOP和IoC这两个会要讲很多的时间,所以我们知道这两个非常重要特性,这两个特性的加入会使它的程序开发,变得异常的简单,很多原来需要管的事情,就通过AOP和IoC把它简化了。
- 除了这两个以外,它的另外一个改进就是我们上面写的,它用XML配置Bean对象。
就是配置组件Bean对象其实是我们说的组件,在之前的J2EE的标准中间,所有的配置需要靠用代码来写,就在这个1.4版本的时候,它是所有的配置需要靠代码来写的,那个时候就要写一个,简单的hello程序,大家知道入门一个框架,或者入门一个程序语言,第一个程序都写的是hello是吧,你简简单单在打出一个hello,在J2EE的1.4版本中间,需要写100多行代码,其中99行代码都是用来写配置,我们配置这个容器,配置组件能在这个容器里跑出来,然后组件跑起来以后就打了一行,hello出来所以虽然,这些代码在之后,在做其它的工程时候是可以重用的,但是J2EE的一个臭名昭着的地方就是它起步慢,你要打个hello先要搞,清楚那100行代码是怎么回事,你才能把个hello打出来。
JavaScript
💻所以Spring框架首先改变这一点,就是它不再用代码去写这个配置,而是用文件去写配置。当时用的就是XML文件,文件去写配置的好处在于什么,配置在运行的时候是可以改的,我代码写好了以后,如果我想修改配置,我不需要重新编译打包这个东西,而仅仅去修改它的XML文件就可以了,当然这是一个很大的特性,当然后来它发现这也是一个很大的弊病。因为它会有安全性的问题,我的代码部署上去以后,如果安全没控制好,别人把你的XML一改了,你整个系统就完蛋了,所以后来它也慢慢的收回了这样一个特性,但在当时这是一个革命性的进步,加上它的AOP和IoC,大家觉得Spring的推出,真的是耳目一新。
💻Spring的其它部分来说,它同样支持了,我们在J2EE中间的相应的规范,比如说访问数据库的JDBC,这个是一定要的,比如说Web部分的一些的,HTTP Request的一部分的,规范,它都是支持的也就是我们在前端,Web Container的规范,它选择性的支持了一部分,这是第一版的Spring。
竞争者的重要性
💻第一版的Spring发布了以后,大家会发现在Spring的,结构上去开发一个应用,比在J2EE上的去开发一个应用,要简单很多,而且工作量也要小很多,所以J2EE就意识到这个问题来了?
原来是没有竞争者,原来是我定规范,然后大家都在我的规范底下去开发东西,现在有人只选择我一部分规范,还有一部分规范,不遵循我的还推出了一些新的概念,来跟我竞争怎么办,我就开始改规范,人家好的我就来学。
💻所以JavaEE的5版本。
- 它首先做的一件事情,就是跟Spring一样,改成配置的方式来配置组件,也就是它的EJB的3.0,这样的话它就在配置的部分来说,跟Spring是完全一样的。
- 但是这时候它还没有把它,的IOC和AOP引进进来。
- 但是它提出了一些新的概念。
💻💻比如说我们在SpringSpring框架中间,大家可以看到它有支持ORM的框架,比如说Hibernate, MyBatis,那这个时候,基本上你的程序要是写的是Hibernate,或者写的是MyBatis,就是跟绑死了的,所以J2EE说我是定义规范的,我就定一个新的规范叫做JPA。
💻这个JPA的规范,所有的ORM,都通过JPA的方式去访问,这样的话你无论是用Hibernate还是用MyBatis,只要遵循JPA的规范,你的代码就都可以去跑(MyBatis还没完全支持JPA),这就是规范的力量。
💻那同时它不仅仅引进了新的这个JPA,它把 Web Service的部分进行了加强,Web Service部分,在之前一直是J2EE,走在了Spring的前面,Spring这时候还在做,它内源性的东西,还没有关注Web Service的部分。
💻2006年10月份,Spring的框架,发布了第二个版本,第二个版本它把XML的配置进行了,大幅度的简化,也就是最开始的XML。
💻它没有最开始的是用DDT来配置的,很麻烦。所以在2006年的10月份的,第二个版本的Spring框架中间,用了Schema来配置XML,这就是XML的进步,所以Spring也跟它进步了。
💻除了这个特性以外,大家可以看到它引入了很多,在JavaEE中间的规范,原来没有JPA,JavaEE做了JPA这个挺好的,我Spring也支持JPA是吧,所以它就它选择性的认为,在JavaEE中间好的规范,我就拿进来,这样的话我在Spring框架中间,可以用JPA去写代码,就无需要关注你是MyBatis,还是Hibernate了。
💻当然它在表现层增加了更多的插件,这些东西其实有一些是J2EE的规范,比如说JSF和JSP,这是在J2EE中间,做前端表现层的规范。它也有很多不是J2EE的规范,比如说像Struts WebWork等,这些不是J2EE的规范。
Spring其实比J2EE的规范,提供了更大的灵活性,在当时我们称这个Spring框架,叫做SSH,------就是S truts,S pring,H ibernate
💻💻SSH构成一个,最简单的构成应用的这样的一个架构,我们可以看到Spring的框架,其实是在JavaEE的规范之外,提供了另外一种可能,当然它也在不断的吸收JavaEE的这些好的东西,这是在06年的10月份。
07年的11月份,Spring的框架,有了一次决定性的改变,这不是一个大版本数,而是一个小版本数2.5,但我们为什么把它提出来讲,是因为从此Spring的框架,引入了注解配置,注解配置的来源是来自于我们,之前的JavaSE 5,因为JavaEE5和JavaSE5,是同步发行的,就是JavaSE,每一次升级之后,就会跟着会有一次JavaEE的升级,JavaSE5的一个重大的升级,就是引入了注解,就是我们在类前面用@去标志注解,方法前面用@去标注注解,在JavaSE5之前是没有的。
标注注解引入到了,JavaSE的库里头,Spring框架看见了,觉得这个东西非常有用
- 它可以用来写我们的配置,之前的配置是用XML写的,大家知道XML很麻烦,XML有一个是一对一对的,而且XML那一对里头还要写有意义的东西,所以往往XML会弄到好大一串,这样的一个东西其实看起来是很麻烦的,写起来也很麻烦,改成注解来写的话,我想配哪个类 我想配哪个方法,在类前面,和方法前面直接写。
- 而且配置和代码合成了一体,它的好处就在于说如果我的代码改变了,我看我的配置是不是会受到影响,如果我的配置改变了,我的代码是不是会受到影响,从程序员的维护来说提供了极大的便利性,如果是分开的你把代码改了,如果改配置你还去找那个,XML在什么地方很麻烦,这是一个革命性的改变。
不仅仅是用注解来写配置,更大的改变是它采取自动扫描的方式
我们知道在Java的库里头,Java的代码中间,如果加了注解的话,Java的类在Load的时候,在装载的时候是可以把注解读出来的,因为Java是具有反射机制的是吧,这种语言所以它可以支持自动扫描,也就是我不再需要去配置说,这个东西在什么地方了,我只要配置说这个东西,可能在某个目录底下,比如说我定个根目录好了,在整个项目的根目录底下,它会自动去扫描,说什么类,有加了这样的一个注解,我就把它作为我们的配置读进来,这样的话会使得什么,会使得我们的配置又变得更少了,很多东西我们不需要写,只要告诉它说你去扫,找到了那就有没找到就没有这个配置。
💻💻所以用注解和用自动扫描的方式的引入,使得Spring的配置,大幅度的减少。减少了70%以上,剩下的部分就基本上靠注解,和自动扫描去完成,除了这个以外它还引入了测试框架,因为我们知道任何一个东西,如果不能测试的话,这个东西不是一个成熟的东西,它在Spring框架中间,引入了我们称为单元测试的JUnit的框架和TestNG的框架,这是Spring框架的一次脱胎换骨的变化。
它的IoC和AOP,一直是领先于JavaEE的规范的,引入了这样的一个机制以后,它在配置的是大幅度的优于JavaEE的框架。
4. JavaEE发展历程(2009-至今)
眼睁睁的看着Spring 🐂B起来,JavaEE就着急了,怎么办?
就学呗!
💻Spring干什么我就学什么,所以在JavaEE的6版本中间,它把Spring框架的两大法宝------IoC和AOP我学过来定了两个规范,叫做CDI和DI。
我们有时候叫做IoC,有时候叫做Dependent,Injection,叫做依赖注入,或者说控制反转是Spring发明的,依赖注入是Java,发明的两个东西是同一个事。
💻是因为它不能表现出来我从抄过来的,所以它发明了一个新的词叫做DI,其实是一码事就把它的,AOP和IoC把它抄过来了,变成了JavaEE的规范,不仅仅是在这里,在JavaEE的这个版本中间,其实它有加入了,我们在后面看到的Restful风格的API,也是基于JSON的Restful API,所以在Web Service的。
在面向服务的这一个部分来说,JavaEE永远是走在前面的,走在Spring的前面的,Spring在不断的,跟JavaEE规范中间,关于Web Service的,这部分的发展。
但是在内源性上头,比如说配置IoC,AOP这些东西,Spring是走在JavaEE前面的,所以JavaEE在跟着Spring来学,这些内源性的东西,AOP和IoC被JavaEE学去了。
Spring 眼睁睁的看着 JavaEE 抄自己的东西,怎么办?
💻Spring又放了一个大招,就是它在2009年的12月份,引入了一种新的配置方式,叫做Java配置。
💻用程序来写配置,我们说在JavaEE的最开始的时候,就是用程序写配置 ,那时候被人诟病说我写一个hello,要写100多行代码,所以Spring框架改用XML来做配置 ,是用注解来做配置,大幅度减少了配置的方式,然后JavaEE把它学过去了。
这时候它又发现Spring又返回来,又开始用代码来写配置了,为什么要用代码来写配置,因为它会发现默认配置是有问题的,就是我加了注解加了自动扫描以后,它其实是一个默认配置,我会去默认扫描说有注解的那些东西,来作为我的配置,但是有些时候我不能用默认配置,就是我一定要告诉它说我虽然那里,有这个东西但我不能用它,那怎么办?
传统方式,它之前的方式是要用XML来写的,用XML来写XML的弊病始终是在那,就是它写起来麻烦,而且它的安全性不好,把它程序做好以后,人家是可以去改XML的。
所以从3.0开始,加入了一个新的特性------就是它用Java代码来写(最原始的方式)。
但是这时候它并不是用Java代码,去写所有的东西,因为Java代码去写,就必须要显式声明的。就是我不能用默认的这些东西,我改用Java代码去写,这样的好处在于说:
- 第一你写配置时不容易出错,因为Java代码是要编译的;
- 第二它编译完了以后配置是不能改的,所以它的安全性等等这方面会更好。
当然它在内源性的部分来说,会增加更多的东西,比如说它把AOP上面,把AOP的特性,从原来的单纯的AOP ,改成了AspectJ 也可以支持,所以它把AOP分成了两个------AOP和Aspects,在类的加载上头加了------Instrumentation,这使得在Java类被加载的时候,可以做一些桩,来做一些额外的这些工作,当然我们其实用的比较少。
其它的部分来说加入了,Expression Language,使得它可以用描述语言,去定义一些更复杂的配置信息等等。
还有,它最下面加了一个Test,2.5开始有了Test,所以3.0的结构上最下面是Test,然后是Core然后是,Core上面支持的,Core上面支持的IoC,然后AOP,然后是访问数据的一块,和做Web的这一块,这是3.0的版本。
此时!JavaEE又意识到了Spring 又🐂B了,所以说。
13年6月份的时候发布的7里头增加了一个,现在为止影响很深的变化,JavaEE7支持HTML5, WebSocket,JavaEE8支持响应式编程。
这是在2013年------10年前,JavaEE已经加入了响应式编程的规范,支持HTML5,所以大家可以看到在这一块,Web Service响应式,编程这一块,JavaEE的规范永远是,走得非常的前卫的。
Spring这个部分来说,它在4.0版本其实做的改变不大,你可以看到从结构上来说没有太大的改变,支持了条件化配置,但是我们把4.0提出来,中间是因为4.0中间的,有一个小版本,做了一个革命性的变化,大概是4.2还是4.3,它引入了SpringBoot。
SpringBoot的引入使得------Spring项目的配置,再大幅度的减少。
也就是说原来是用注解自动扫描,加上Java的代码,你还需要写一些的配置,包括说你的依赖,因为我们知道Java代码的最讨厌的地方,就是说你要依赖很多Jar包,原来的管理方式来说是有一定的问题的,因为我要引入一个Jar包,这个Jar包还要依赖其它的Jar包,那要一堆出来,然后这些Jar包还会相互打架等等这些问题依赖的,引入配置的这些问题。
在SpringBoot中间通通一键性的解决了 ,SpringBoot用一种默认的方式,去管理这些依赖,以及这些依赖的这些配置,这是在Spring4.3引入的SpringBoot的工程放进来了,从此Spring就跟SpringBoot一起了,这再没有人有了SpringBoot以后,再没有人想直接用Spring,而是通过SpringBoot,去管理Spring的工程,所以就把Spring和SpringBoot,画上了等号。
JavaEE的8的版本,我们可以看到它引入了更多的JSON的这些特性,这个版本引入了响应式编程,这个版本是一个划时代的意义,它的化时代的意义在于,JavaEE的版本号,永远停在了JavaEE8。
因为这时候发生了什么,发生了Sun公司,被Oracle公司收购了,然后Oracle公司发现,Java这个东西,是一个不赚钱的东西,为什么不赚钱,因为它是规范而不是产品,我辛辛苦苦定义了一堆的规范,然后让一堆的公司去开发它们的产品,然后它们产品在卖钱,规范也不卖钱,是吧,所以这就是为什么Sun公司,最后会被Oracle公司收购了。
Oracle公司做了一个决定,既然你是个规范,我是一个商业公司,我的商业公司,好像不适合于全力,去支持这样的一个规范,它就把这个东西交给了阿帕奇的基金会,大家知道阿帕奇是一个开源的基金,由它去维护这样的一个规范,而Oracle公司作为一个商业公司,着力去在规范上面去开发,自己的产品去赚钱,是吧,所以JavaEE的,版本停留在了8。
为什么?因为JavaEE是Sun公司的注册商标,它没把商标转给阿帕奇基金会,它只把规范转给它了,所以阿帕奇的基金会,不能再使用JavaEE,来标识后续的产品,它们就做了一个投票,投票的结果是它把这个名字,改成了JakartaEE,所以JakartaEE也有JakartaEE8,JakartaEE8就是JavaEE8,只不过是JavaEE8,被移交给了这个阿帕奇基金会,被改成了JakartaEE8,后来JakartaEE9包括9.1,都有后续的版本出现。
Spring的框架,在这个JavaEE停止了以后,又发布了一个新的版本,5.0就是跟着JavaEE,去学了响应式编程。
因为响应式编程,是高并发大负载的,一个非常有效的解决的方案。响应式编程我们在面向对象的课里头有提到过,它其实是用的函数式编程,就是函数式编程的方式,这意味着它跟我们传统的命令式编程的方式,是完全不同的,设计方法和编程的方式,传统的整个链的,Spring的框架里头的东西,通通都不能用了,Spring框架5.0开始,大家可以看到Spring的框架,被切成了两半 一半是传统的,我们说:
- 命令式编程的,它叫做Servlet Stack
- 函数式编程的,它叫做Reactive Stack------响应式的技术栈。
全套的东西都是不同的,从最上面到最下面都完全不同,唯一相同的就是上面看到,那个SpringBoot是一样,因为SpringBoot是没内容的,SpringBoot就是负责去管理,依赖管理配置信息的,所以它跟具体的技术的特征,是没有什么太大的关系,但是下面的所有东西全部都不同,因为它是两种完全不同的编程的方式。
我们之前的课,一直着重在介绍Servlet Stack,我们要讲Reactive Stack,因为这个是在近5年来,会越来越成为一种主流的不是主流的,会成为一种有影响力的编程的方式,它到目前为止还没有,撼动Servlet Stack,这一条线的应用。因为作为函数式编程来说,我们其实在设计方法上头,并没有像我们在命令式,编程的设计方法中间那么成熟,就换句话说,我们知道所有的东西,你基本上用命令式的编程方式,是能够把它做出来的,但是它用函数式编程是不是能做出来,数学上说是可以,万事万物都可以函数化是不是,万事万物都是函数的转换,都是从输入的值域,转成这个转成输出的域是吧。
但是实际上,你再去用函数的编程,去解决问题的时候,还有很多事情我们从来没做过,所以是发展的趋势,但是它是不是能解决所有的问题,我们现在还在探索中。JavaEE的后续的这个介绍的话,它依然在不断的来扩展这个新的功能,我们就不仔细讲了因为它已经,转换到这个阿帕奇的基金会了,转换到阿帕奇基金会以后,其实阿帕奇基金会还需要一段时间来稳定,所以说它们在后续的,**8和9版本中间,并没有做出一些革命性的变化,也就是它最后一次革命性变化,是把响应式的编程,引入到了 JavaEE的规范中间,**到目前为止9版本中间,并没有什么特别大的这样,一个东西所以我们就不讲。
我们再说最后的Spring6.0,6.0的三个革命性变化。
- 第一把XML的配置彻底成为过去式 。因为我们可以看到它的发展的过程来说,慢慢的用注解替代XML,减少XML的使用 ,显式的还会用XML做,然后用Java的程序来替代XML的使用。
- 第二个是它会全面支持JakartaEE 9,也就是JakartaEE 9提出的一些规范,在Spring6.0中间,可能会有选择的吸收进来。
- 第三是它会支持云原生的,SpringBoot3.0,因为我们刚才说了SpringBoot是,一个管理配置和管理依赖的,所谓支持云原生的SpringBoot3.0,意味着说它会全面微服务化。
因为我们刚才说了云原生的这样的一个结构,无论是我们在设计上头和实现上头,都得要考虑微服务化和容器化,就是Docker化这样的一个考量,这样的话才会根据你的负载的差异,来动态的弹性调整,在服务器端的应用的配置。
我们把两条线把它画了出来,大家可以看到,Spring和JavaEE其实是相生相克的。
两产品线在JavaEE的规范中间,在JavaEE的市场中间,其实是两条平行线,但是中间大家在不断的,吸收对方的一些东西,然后放到自己的产品里头来,又不断的提出新的东西,去对对手产生这样的一个竞争的优势,我们希望JavaEE的,规范被移交给阿帕奇基金会以后,还能提出一些,革命性的这些东西出来,那同样Spring的框架,从一开始所提出的,轻量化设计的这样一个想法,在今天的云原生的,这样一个架构上,其实是有优势的,因为云原生会更加讲究,每一个单独的,这样的服务的轻量化,你才可以很方便的,在服务器架构上的,去弹性化的部署,所以这样的一个发展,我们可以看到已经精彩了,差不多接近30年,未来的话有两个产品线在这么不断的竞争,我们希望看到说在未来的几十年里头,我们还能看到Java,像今天这样在整个后端服务器市场中,占有差不多半壁以上的江山。
当然我们今天有很多新的语言在跟它竞争,大家知道目前它面对最大的竞争是哪种语言,------Go语言goroutine语言,跟 Java语言,最大的优势就是在它,是完全基于云来设计的,云原生的这样的一个应用,我们可以看到因为Java,无论是JavaEE还是Spring,承载了太长的历史今天在云原生的架构上头,Go语言对于Java语言来说,是有一定的优势的,但是我们相信Spring已经首先做出了反应,也就是它会在SpringBoot中间,完全支持云原生的这样一个结构,JavaEE我想也会做出反应来,因为这是反应了这个市场,之所以会精彩了30年,就是因为这个市场,给很多的不同的产品,提供了机会,让这些产品去竞争,相互促进才会发展成为今天这个样子,所以这是我们花点时间,来简要的讲了一下,JavaEE的规范和Spring发展的历史。
5. Java的Spec数目与网络结构
-
我们可以看到随着几十年的发展,JavaEE规范已经非常的庞大了,到最后一个官方版本,就是JavaEE8的官方版本来说,已经达到了40个规范。
-
而Spring的框架采取的策略就是,我不要那些所有的规范。
到今天就是Spring5.0里头,它仅支持40个规范中间的9个,它有选择性的支持了其中的一小部分,特别是它前面,在Web Container那里头的那些规范,EJB里头的EJB的规范,它基本上把它大幅度的给它抛弃掉了,支持这些小部分的规范,加上它自己的特性,Spring的框架从来没有在说我所有东西,都要遵循JavaEE的规范,它相信它自己做出来的东西,终究会成为JavaEE的规范,过去的30年已经有看到JavaEE的规范,中间有学了很多Spring框架的东西,当然Spring的框架东西,也在某些部分来说,超前于JavaEE的规范,我们希望这两个东西,包括未来的go语言,三个东西会相互促进,一起向前发展。
从体系结构上来说,我们最早期的体系结构是这样的,我们把这个应用是部署在服务器上的,按照JavaEE的规范来说,它的服务器是分为Web服务器和应用服务器,Web服务器就是我们说的Web容器的服务器,而应用服务器就是EJB的服务器,Web容器负责渲染我们的HTML,而EJB的服务器是应用服务器,负责我们的应用逻辑,所以它是这么取名的。
用Spring的框架来说,它往往会把Web服务器,和应用服务器合一,因为它没有后面的EJB的容器,所以说如果采用Spring框架来说,其实这两个服务器会合成一个,变成一个更简单的架构,但随着Web技术的发展,我们知道Web技术的发展中间,有一个重要的事件------就是AJAX。我们后面会提到它,也就是在HTML上面加上了,JavaScript,加上了JavaScript以后,HTML不再需要由服务器去渲染产生了,你可以把HTML写成死文件, HTML仅是用来描述格式的,里头的内容靠什么------靠JavaScript。
其实不是JavaEE的标准,但是这是我们知道,在Web发生了一个重大的改变,这样的一种方式就使得说:
- 我们可以把HTML和JavaScript,把它放到浏览器里头。
- 然后在浏览器里头运行,JavaScript去访问我们的服务器。
- 服务器去做我们的应用逻辑,得到数据把数据,送给前面的浏览器。
- 前面浏览器用JavaScript,去解析这些数据,再来决定这些数据如何在界面上去显示。
所以界面层的事情被完全交给了浏览器。
靠浏览器的JavaScript去完成,服务器已经完全脱离了界面层的任何职责,这时候你会发现JavaEE,的Web Container,就没什么用了,是吧,因为它不需要在服务器端,生成HTML的网页了,服务器端就是做应用逻辑的事情,接收前端发来的请求,去做业务逻辑把得到的,结果用数据我们现在数据的格式是JSON的方式,送回前端。
所以今天的结构,在Spring架构上又形成了,我们看到了这样的一个结构,只不过是此时的Web服务器,不是彼时的Web服务器了,此时的Web服务器,是个单纯的Web服务器,就是单纯用来存, JavaScript的代码,和HTML的一个单纯的文件服务器,就是死服务器没有任何动态的东西 ,它的作用就是当客户端来访问的时候,把HTML和JavaScript,传到前面的浏览器上去,然后前面浏览器再去访问这个应用服务器,去拿到逻辑和数据,而这时的应用服务器,其实是用JavaEE的标准的Web Container来完成,所以它更会觉得EJB Container没有什么意义了。
Spring 为什么说 JavaEE垃圾??
JavaEE的标准到今天我们看到,最新的9的版本中间,还是有EJB的Container,这就是死不改悔,拖了30年,一直被Spring来刺说,你EJB没有任何意义,但是它就坚持了30年还在做,这个东西当然可能坚持有坚持的好处。
这是这样的一个结构,我们说到当负载大的时候,当负载大的时候大家想到了一个解决方案,就是把服务器增加------无论是Web服务器,还是应用服务器都增加。
但这个简单的方式会带来成本的增加,所以从成本的核算来说,弹性增加才是更好的,而且弹性增加,增加的其实并不是给所有的应用,都平等的分服务器,而是我们把其中高负载大并发的那部分应用分给更多的计算资源给它,而那些平时不是负载很大的东西,分更少的资源给它,这才是一个更好的使用,这样的服务器资源的方式。
所以在分布式应用的这样的一个前提下,在云原生的情况下头,我们要把应用做到,如何让服务器能够弹性的,给它分配资源,这就是我们所说的云原生的结构。
考虑你的代码,将来是会被弹性的分配的,你如果不这么写代码是,没办法做到弹性分配的,以后如果去到互联网公司去就业的话,它们基本上在高并发大负载的时候,都是弹性分配的,这样的一个云原生的架构来写代码,这是我们总体的这样的一个结构。