大约20年前,程序员们使用“企业级Java Bean”(EJB)开发企业应用,须要配置复杂的XML。
在二十世纪初期,新兴Java技术——Spring,横空出世。使用极简XML和POJO(普通Java对象),结合EJB的替代品(如Hibernate),Spring在企业级Java开发上占据了绝对领先地位。
可是,随着Spring的不断发展,当初的XML配置逐渐变得复杂庞大,成了累赘,遭众多程序员“诟病”。后来,Spring推出了JavaConfig项目,使用声明式的注解,大量减小了显式的XML配置。
然而,问题到这里,并无结束。html
J2EE使用多层的分布式应用模型,以下图所示:java
应用逻辑按功能划分为组件,各个应用组件根据他们所在的层分布在不一样的机器上。事实上,sun设计J2EE的初衷正是为了解决两层模式(client/server)的弊端,在传统模式中,客户端担当了过多的角色而显得臃肿。
J2EE平台由一整套服务(Services)、应用程序接口(APIs)和协议构成,它对开发基于Web的多层应用提供了功能支持。
以下是对J2EE中的13种技术规范进行简单的描述[3]:python
J2EE提供了"编写一次、随处运行"的特性、方便存取数据库的JDBC API、CORBA技术以及可以在Internet应用中保护数据的安全模式等等,同时还提供了对 EJB(Enterprise JavaBeans)、Java Servlets API、JSP(Java Server Pages)以及XML(标准通用标记语言的子集)技术的全面支持。git
为了解决这些问题,出现了Struts框架,它是一个完美的MVC实现,它有一个中央控制类(一个Servlet),针对不一样的业务,咱们须要一个Action类负责页面跳转和后台逻辑运算,一个或几个JSP页面负责数据的输入和输出显示,还有一个Form类负责传递Action和JSP中间的数据。JSP中可使用Struts框架提供的一组标签,就像使用HTML标签同样简单,可是能够完成很是复杂的逻辑。今后JSP页面中不须要出现一行<%%>包围的Java代码了。
但是全部的运算逻辑都放在Struts的Action里将使得Action类复用度低和逻辑混乱,因此一般人们会把整个Web应用程序分为三层,Struts负责显示层,它调用业务层完成运算逻辑,业务层再调用持久层完成数据库的读写。
使用JDBC链接来读写数据库,咱们最多见的就是打开数据库链接、使用复杂的SQL语句进行读写、关闭链接,得到的数据又须要转换或封装后往外传,这是一个很是烦琐的过程。程序员
这时出现了Hibernate框架。它对JDBC提供了封装。Hibernate的O/R Mapping实现了POJO 和数据库表之间的映射,以及SQL的自动生成和执行。
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了很是轻量级的对象封装,它将POJO与数据库表创建映射关系,是一个全自动的orm框架,hibernate能够自动生成SQL语句,自动执行,使得Java程序员能够为所欲为的使用对象编程思惟来操纵数据库。 Hibernate能够应用在任何使用JDBC的场合,既能够在Java的客户端程序使用,也能够在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate能够在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。[8]
如今咱们有三个层了,但是每层之间的调用是怎样的呢?好比显示层的Struts须要调用一个业务类,就须要new一个业务类出来,而后使用;业务层须要调用持久层的类,也须要new一个持久层类出来用。经过这种new的方式互相调用就是软件开发中最糟糕设计的体现。简单的说,就是调用者依赖被调用者,它们之间造成了强耦合,若是我想在其余地方复用某个类,则这个类依赖的其余类也须要包含。程序就变得很混乱,每一个类互相依赖互相调用,复用度极低。若是一个类作了修改,则依赖它的不少类都会受到牵连。 为此,出现了Spring框架。github
MyBatis是另一个普遍使用的ORM框架。本来是Apache的一个开源项目iBatis, 后更名为MyBatis 。MyBatis的核心在于管理 POJO 与 SQL 之间的映射关系。MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
Mybatis框架的架构以下图:web
Mybatis框架的架构
MyBatis相对于Hibernate,主要优点是能够进行更为细致的SQL优化。
关于MyBatis,详细了解可参考:http://www.mybatis.org/mybatis-3/zh/index.htmlredis
Spring Framework:
Core support for dependency injection, transaction management, web applications, data access, messaging, testing and more.
Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson建立。简单来讲,Spring是一个分层的JavaSE/EE full-stack(全栈式) 轻量级开源框架。spring
Rod Johnson在2002年编著的《Expert one on one J2EE design and development》一书中,对Java EE 系统框架臃肿、低效、脱离现实的种种现状提出了质疑,并积极寻求探索革新之道。以此书为指导思想,他编写了interface21框架,这是一个力图冲破J2EE传统开发的困境,从实际需求出发,着眼于轻便、灵巧,易于开发、测试和部署的轻量级开发框架。
Spring框架即以interface21框架为基础,通过从新设计,并不断丰富其内涵,于2004年3月24日,发布了1.0正式版。同年他又推出了一部堪称经典的力做《Expert one-on-one J2EE Development without EJB》,该书在Java世界掀起了轩然大波,不断改变着Java开发者程序设计和开发的思考方式。
没有最好的架构,只有最合适的架构。循证架构是《Expert One-on-One J2EE Development without EJB》(Rod Johnson,)一书中推崇的架构思路,用俺们的话说就是摸着石头过河,找最适合本身的架构。
咱们曾经在无数的书籍和文章中看到,EJB是J2EE的核心技术之一。而Rod Johnson居然宣称,绝大多数的J2EE应用根本不须要EJB。
Rod Johnson引领了一场J2EE领域影响深远的变革。Spring和Hibernate,IoC和AOP,轻量级架构等等。还有更重要的一点,是遵循一切实事求是的“循证架构”的问题解决的方法论哲学。sql
Rod Johnson认为,应该是基于实践的证据、来自历史项目或亲自试验的经验,而不是任何形式的偶像崇拜或者门户之见。[10]
“循证哲学”(基于实践的证据、来自历史项目或亲自试验的经验)、“实事求是”的工做方式——这本来就应该是程序员的工做方式。
“认识来源于实践,而又运用于实践”。 ——马克思
人的认识来源于实践,是随着实践的发展而发展的。经过实践得出的认识,只有做用于实践并经过实践的检验,才可以肯定认识的正确与否。
循证架构思想来源于”循证明践“。任何涉及模式,架构模式,编程范式(过程式,面向对象式,函数式,逻辑式,面向服务式)的问题,都是基于解决某个实际业务场景才有其实质存在的意义。
循证明践(Evidence-Based Practise),亦为循证学。本意是"基于证据的实践",其理念始于20世纪末发展起来的循证医学。最初意指医生"将当前所能得到的最佳研究证据与自身的专业技能及患者的价值观整合起来进行治疗"。此后,它便以迅雷不及掩耳之势席卷了整个医疗卫生领域,并不断向邻近学科渗透,造成了循证心理治疗、循证教育学、循证社会学等数十个新的学科领域。
在程序开发里不一样模块之间信息的沟通是经过对象传递完成的,而对象可否顺利传递就是要合理的构建好对象,而管理好对象的构建方式就能管理好对象传递,spring主要就是解决这个问题的。spring提供一个容器,咱们在xml文件里,或者经过注解的方式(注解的方式是经过反射机制实现)定义各个对象的依赖关系,由容器完成对象的生命周期的管理(建立,运行,销毁)。
Spring框架创建在IOC和AOP技术之上。
IOC: Inversion of Control,控制反转,就是由容器控制程序之间的(依赖)关系,而非传统实现中,由程序代码直接操控。 当咱们的代码里须要使用某个实例的时候就能够直接从容器里获取。对象的实例化由spring容器负责搞定,因此它被称为控制反转,控制反转的意思就是原本属于java程序里构建对象的功能交由容器接管,依赖注入(DI)就是当程序要使用某个对象时候,容器会把它注入到程序里。Spring IOC有三种注入方式:接口注入、setter注入、构造器注入。
AOP: Aspect Oriented Programming,面向切面编程,就是把可重用的功能提取出来,而后将这些通用功能在合适的时候织入到应用程序中,好比事务管理、权限控制、日志记录、性能统计等。经过预编译方式和运行期动态代理实现业务逻辑模块之间的隔离,使业务逻辑模块间的耦合度极大化地下降,提升程序可重用性和开发的效率。使用 AOP 后,公共服务 (比 如日志、持久性、事务等)就能够分解成方面并应用到域对象上,同时不会增长域对象的对象模型的复杂性。AOP的工做模式以下图所示:
Spring框架至今已集成了20多个模块。这些模块主要被分以下图所示的核心容器、数据访问/集成,、Web、AOP(面向切面编程)、工具、消息和测试模块[5]:
Spring总体架构
核心部分分为4大块,spring-core, spring-beans, spring-context, spring-expression. 其中core和bean是整个框架的核心,提供了基础的DI和IoC功能。 Context创建在core和beans模块之上,提供一种相似JNDI且以框架的方式来操做对象的方式。Context模块从beans模块继承它的功能同时增长了国际化支持,如资源绑定等,同时,Context模块也支持JavaEE功能,如EJB,JMX和基本的远程调用。ApplicationContext接口是context模块的焦点。expression是一种很强大的expression language,支持在运行时查询和操做对象的属性,咱们会在后面的文章中举些例子来讲明spring expression language的用法。
Aop模块提供了面向切面编程的实现,和AspectJ集成。
Messaging是spring4新增长的模块,包含了一部分主要的基于message的应用的实现。
Data access顾名思义,是spring对数据层提供的支持,是功能比较丰富的模块。提供了包括JDBC,事物,ORM,JMS等一系列实现。
Web模块主要提供面向web的一些实现,例如多文件上传,servlet监听器以及spring mvc方面的支持。
Test模块主要是针对spring的各个模块作各类各样的测试,包括单元测试、集成测试等等。
通常代码的操做对象是数据。元编程操做的对象是代码。
元编程一言以蔽之,就是用代码生成(操纵)代码。在运行时建立和修改代码而非编程时,这种程序叫作元程序。而编写这种程序就叫作元编程。元编程是用代码在编译期或运行期生成/改变代码。元编程是现实世界的抽象的利器。
元编程技术在多种编程语言中均可以使用,但更多的仍是被应用于动态语言中,由于动态语言提供了更多的在运行时将代码视为数据进行操纵的能力。
Java 5中提供了Annotations,它是Java的metadata。Java应用中的元数据在早期Java版本中,通常使用属性文件、XML,后来注解出现了,就都用注解了。
Java经过反射机制实现元编程。反射是促进元编程的一种颇有价值的语言特性。
常见的开发语言均能作到元编程,Lisp就不用多说了,C的Marco,C++的Template,Java的Annotation,C#的Attribute、Reflection、CodeDom和IL Emitter,各类脚本语言(如js、python)的eval,甚至连Unix/Linux的shell脚本也能。
元编程常见的应用场景不少,扩展语法、开发DSL、生成代码、根据特定场景自动选择代码优化、解决一些正交的架构设计问题、AOP等等。
元编程,是对语言自身再向上一层抽象。
Spring IOC有一个很是核心的概念——Bean。由Spring容器来负责对Bean的实例化,装配和管理。XML是用来描述Bean最为流行的配置方式。Spring能够从XML配置文件中读取任何类型的元数据并自动转换成相应的Java代码。Spring改变了java的编程模式。
随着Spring的日益发展,愈来愈多的人对Spring提出了批评。“Spring项目大量的烂用XML”就是最为严励的一个批评。因为Spring会把几乎全部的业务类都以Bean的形式配置在XML文件中,形成了大量的XML文件。使用XML来配置Bean失去了编译时的类型安全检查。大量的XML配置使得整个项目变得更加复杂。Rod Johnson也注意到了这个很是严重的问题。
当随着Java EE 5.0的发布,其中引入了一个很是重要的特性——Annotations(注解)。注解是源代码的标签,这些标签能够在源代码层进行处理或经过编译器把它熔入到class文件中。在Java EE 5之后的版本中,注释成为了一个主要的配置选项。Spring使用注释来描述Bean的配置与采用XML相比,因类注释是在一个类源代码中,能够得到类型安全检查的好处。能够良好的支持重构。
JavaConfig就是使用注释来描述Bean配置的组件。JavaConfig 是Spring的一个子项目(详细了解可参考:http://docs.spring.io/spring-javaconfig/docs/).
后来,当@Annotation出现了,大部分技术、框架就纷纷放弃了XML配置文件,改成使用Annotation来管理配置信息。
Spring有2种经常使用的配置方式:
Spring的XML配置方式是使用被Spring命名空间的所支持的一系列的XML标签来实现的。Spring有如下主要的命名空间:context、beans、jdbc、tx、aop、mvc等。
使用XML来配置Bean所能实现的功能,经过JavaConfig一样能够很好的实现。以前咱们都是在xml文件中定义bean的,好比:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="helloBean" class="com.hello.impl.HelloWorldImpl">
</beans>
其实咱们可使用注解来完成这些事情,例以下面的代码,完成的功能和上面的xml配置的功能是同样的:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import com.hello.HelloWorld; import com.hello.impl.HelloWorldImpl; @Configuration public class AppConfig { @Bean(name="helloBean") public HelloWorld helloWorld() { return new HelloWorldImpl(); } }
使用@Bean注解,来标识此方法构造出一个由Spring容器管理的bean。Spring对Java配置的支持是由@Configuration注解和@Bean注解来实现的。由@Bean注解的方法将会实例化、配置和初始化一个新对象,这个对象将由Spring的IoC容器来管理。@Bean声明所起到的做用与<bean/> 元素相似。被@Configuration所注解的类则表示这个类的主要目的是做为bean定义的资源。被@Configuration声明的类能够经过在同一个类的内部调用@bean方法来设置嵌入bean的依赖关系。
通常在一个大型工程项目中,若是将全部的bean都配置在一个xml文件中,那么这个文件就会很是的大。因此通常会将一个大的xml配置文件分割为好几份。这样方便管理,最后在总的那个xml文件中导入。好比:
1 <beans xmlns="http://www.springframework.org/schema/beans" 2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://www.springframework.org/schema/beans 4 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> 5 6 <import resource="config/customer.xml"/> 7 <import resource="config/scheduler.xml"/> 8 9 </beans>
可是如今咱们也可使用JavaConfig来完成一样的工做了:
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; @Configuration @Import({ CustomerConfig.class, SchedulerConfig.class }) public class AppConfig { }
@Configuration能够被认为是至关于XML的< bean / >元素。
Spring在2.5版本之后开始支持用注解的方式来配置依赖注入。能够用注解的方式来替代XML方式的bean描述,能够将bean描述转移到组件类的内部,只须要在相关类上、方法上或者字段声明上使用注解便可。使用JavaConfig的配置方式,一行XML代码都不须要,什么web.xml,Application-context.xml,Beans.xml,通通再见。
在 Spring XML中, 启动注解注入bean,经过以下标签实现:
<context:annotation-config/>
在 JavaConfig中, 等同于 @AnnotationDrivenConfig注解。
代码示例:
@Configuration
@AnnotationDrivenConfig
public class Config { // may now use @Autowired to reference beans from other @Configuration classes, XML, etc }
使用@ComponentScan注解,等同于在 Spring XML中的
<context:component-scan/>
代码示例:
package com.company.foo;
@Service
public class FooServiceImpl implements FooService { private final FooRepository fooRepository; @Autowired public FooService(FooRepository fooRepository) { this.fooRepository = fooRepository; } // ... } package com.company.foo; @Repository public class JdbcFooRepository implements FooRepository { private final DataSource dataSource; @Autowired public FooRepository(DataSource dataSource) { this.dataSource = dataSource; } // ... } @Configuration @ComponentScan("com.company") // search the com.company package for @Component classes @ImportXml("classpath:com/company/data-access-config.xml") // XML with DataSource bean public class Config { }
在配置类中使用上述的配置,咱们就能够在代码里调用service方法了:
public class Main {
public static void main(String[] args) { JavaConfigApplicationContext ctx = new JavaConfigApplicationContext(Config.class); FooService fooService = ctx.getBean(FooService.class); fooService.doStuff(); } }
Spring框架项目的出发点是为了解决被其余框架所忽略的部分。在J2EE各个具体领域,都有不少出色的解决方案,web框架持久化方案,远程调用工具等等,然而将这些工具整合成一个全面的架构,却困难重重,甚至成为一种负担。spring提供了一个完整的解决方案,将各类专用框架整合成一个连贯的总体的架构。
Spring诞生之初,就是为了解决当初EJB的重量级复杂编程问题。Spring经过轻量级的架构,使用IOC(DI)和AOP,用POJO实现了EJB的功能。但是,Spring使人头疼的繁杂的配置,让开发者陷入了另外一个深渊(世间万物,每每如此)。一开始,Spring使用大量xml配置。Spring 2.5引入了基于注解的组件扫描,消除了大量针对应用自身的组件的xml配置。Spring 3.0 有了Java Config解决方案,能够替代xml。可是,仍是有使用不少Spring的特性,诸如事务管理,SpringMVC,以及集成第三方框架的时候(好比模板引擎:velocity, freemarker, thymeleaf),仍是须要大量的显式配置。配置Servlet和Filter等一样须要在web.xml里面配置。
对了,还有运行调试的时候,须要配置web容器等大量手工劳动。
这些配置,耗去了程序员们的大量的精力和时间,使得生产效率大减折扣。程序员们的大脑不得不在编写业务逻辑代码跟xml配置之间来回切换。
在后面的章节中,咱们将看到Spring Boot对程序员更加简易地使用Spring框架上面所带来的巨大变化,以及对Spring生态体系,各类技术框架的的整合集成。
Spring Boot,简单讲就是牺牲项目的自由度来减小配置的复杂度(“契约式编程”思想,SpringBoot自动配置方案的指导思想)。约定一套规则,把这些框架都自动配置集成好,从而达到“开箱即用”。同时,也支持自由配置。这就是一个很是好的方案了。
Java Web开发涉及的技术比较繁杂,涉及到不少开发框架和工具(Java, Scala, Kotlin, Clojure,Groovy, Grails,Gradle, Maven, JDBC,Mysql, oracle, mongodb, Tomcat,Jetty,Spring,Struts,Hibernate,Mybatis,JPA,JSP,velocity,freemarker,thymeleaf ,Redis,... ),并且它们各有所长,并非一个完善的体系。这对程序员能进行Jave Web开发,带来了必定的技术门槛和学习成本。
有没有一个像“航空母舰(Aircraft Carrier)”式的威力强大的武器,能够整合这一切呢?答案就是:Spring Boot。
SpringBoot让建立独立的,生产环境的基于Spring的应用更加快捷简易。 大部分Spring Boot Application只要一些极简的配置,便可“一键运行”。
SpringBoot的特性以下[1]:
Spring因为其繁琐的配置,一度被人认为“配置地狱”,各类XML、Annotation配置,让人眼花缭乱,并且若是出错了也很难找出缘由。而Spring Boot更多的是采用Java Config的方式,对Spring进行配置。
咱们企业级软件的目标是提供稳定健壮的服务,以实现其商业价值。为了知足这些需求,服务开发者须要可以快速构建和迭代新的应用,同时应用的架构是可扩展的,便携式的,富弹性的,能够进行频繁的更新。SpringBoot正式为此而诞生[2]。
SpringBoot是伴随着Spring4.0诞生的;
从字面理解,Boot是引导的意思,所以SpringBoot帮助开发者快速搭建Spring框架;SpringBoot帮助开发者快速启动一个Web容器;SpringBoot继承了原有Spring框架的优秀基因;SpringBoot使得基于Spring的开发过程更加简易。
Change is inevitable, that's the only constant. Become the Future You Imagine (Rob Mee, Pivotal CEO)[3]
Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员再也不须要定义样板化的配置。经过这种方式,Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。
多年以来,Spring IO平台饱受非议的一点就是大量的XML配置以及复杂的依赖管理。在去年的SpringOne 2GX会议上,Pivotal的CTO Adrian Colyer回应了这些批评,而且特别提到该平台未来的目标之一就是实现免XML配置的开发体验。Boot所实现的功能超出了这个任务的描述,开发人员不只再也不须要编写XML,并且在一些场景中甚至不须要编写繁琐的import语句。
然而,Spring Boot并非要成为Spring IO平台里面众多“Foundation”层项目的替代者。Spring Boot的目标不在于为已解决的问题域提供新的解决方案,而是为平台带来另外一种开发体验,从而简化对这些已有技术的使用。对于已经熟悉Spring生态系统的开发人员来讲,Boot是一个很理想的选择,不过对于采用Spring技术的新人来讲,Boot提供一种更简洁的方式来使用这些技术。
做为当前主流的企业框架Spring,它提供了一整套相关的顶级项目,能让开发者快速的上手实现本身的应用。请看下图“Spring航空母舰”:
目前来讲spring主要集中于spring boot(用于开发微服务)和spring cloud相关框架的开发。spring cloud子项目包括:
SpringBoot项目源码:https://github.com/spring-projects/spring-boot
SpringBoot学习示例:https://github.com/netgloo/spring-boot-samples
版本历史参考:https://github.com/spring-projects/spring-boot/releases
正由于Spring Boot是与Spring一脉相承的,因此对于广大的Java开发者而言,对于Spring的学习成本几乎为零。
在实践Spring Boot时学习重点,或者说思惟方式改变的重点在于:
1)对于REST的理解,这一点尤其重要,须要从设计、开发多个角色达成共识,不少时候都是对于HTTP 1.1协议以及REST的精髓不理解,致使REST被「盲用」而产生一些很差的效果。
2)对于YAML的理解和对于JavaConfig的理解,这两点相对较为简单,本质上是简化了xml文件,并提供等价的配置表述能力。
1.http://projects.spring.io/spring-boot/
2.https://pivotal.io/spring-app-framework#buildanything
3.https://pivotal.io/
4.http://www.infoq.com/cn/articles/microframeworks1-spring-boot
5.http://blog.csdn.net/zeb_perfect/article/details/51945350
6.http://projects.spring.io/
7.SpringBoot官网文档:http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/