参考引用:
https://www.nosuchfield.com/2017/10/15/Spring-Boot-Starters/
http://www.3xmq.com/article/1522809264295
问题一 Spring Boot、Spring MVC 和 Spring 有什么区别?
SpringFrameWork
Spring 框架就像一个家族,有众多衍生产品例如spring core, spring mvc,spring boot与spring Cloud 等等。但他们的基础都是Spring Core ,Spring Core更像是一个“引擎”,ioc 提供了依赖注入的容器, aop解决了面向横切面的编程,然后在此两者的基础上实现了其他延伸产品的高级功能。
IOC原理
IOC(DI):java程序中的每个业务逻辑至少需要两个或以上的对象来协作完成,通常,每个对象在使用他的合作对象时,自己均要使用像new object() 这样的语法来完成合作对象的申请工作。你会发现:对象间的耦合度高了。而IOC的思想是:Spring容器来实现这些相互依赖对象的创建、协调工作。对象只需要关系业务逻辑本身就可以了。从这方面来说,对象如何得到他的协作对象的责任被反转了(IOC、DI)。
IOC所用到的java中重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。
AOP原理
AOP是面向切面的编程,在一定程度上它是面向对象编程的补充。OOP利用继承、封装和多态的特性构建一种由上到下的多层次结构,利用OOP的特性可以轻松地完成各个业务流程的实现,但是对于一些与业务无关的、重复被业务模块所调用的一些逻辑(比如写日志,事务等)如果用OOP来解决会造成业务代码中出现大量冗余的与业务无关的代码,这个时候就可以用AOP来解决。具体做法通过横切某个需要添加公共逻辑的点(即切入点),在这个切面上引入公共逻辑(即通知)。
SPRING是通过动态代理来实现AOP的,SPRING内部提供了2种实现机制
1.如果是有接口声明的类进行AOP,spring调用的是java.lang.reflection.Proxy类来做处理
2.如果是没有接口声明的类,spring是通过CGLIB来实现AOP的
SpringMVC
SpringMVC是一个Spring解决WEB开发问题提供的一个轻量级MVC框架,MVC模式将业务数据的模块(model)与显示模块(view)通过控制器(Controller)解耦。
Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。
通常模型对象负责在数据库中存取数据。
View(视图)是应用程序中处理数据显示的部分。
通常视图是依据模型数据创建的。
Controller(控制器)是应用程序中处理用户交互的部分。
通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。
SpringBoot
学过Spring的都知道,Spring开发有非常头疼的三点:,以启动一个带Hibernate的Spring MVC为例:
1. 依赖太多了,而且要注意版本兼容。这个应用,要添加10-20个依赖,Spring相关的包10多个,然后是Mybatis包,Spring与Mybatis整合包,日志包,json包一堆,而且要注意版本兼容性。
2. 配置太多了,要配置注解驱动,要配置数据库连接池,要配置Mybatis,要配置事务管理器,要配置Spring MVC的资源映射,要在web.xml中配置启动Spring和Spring MVC。。等
3.部署和运行麻烦。要部署到tomcat里面。不能直接用java命令运行。
Spring Boot的哲学是约定大于配置。很多东西可以做成一个规范,来大大简化配置
1. 通过starter和依赖管理解决依赖问题。
2. 通过自动配置,解决配置复杂问题。(如果有些值你没有配置的话,那程序会取一个默认值,换句话说,能取默认值的配置,就不需要配置了。这个默认值就是约定。)
3. 通过内嵌web容器,由应用启动tomcat,而不是tomcat启动应用,来解决部署运行问题。
Spring Boot本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于Spring框架的应用程序。也就是说,它并不是用来替代Spring的解决方案,而是和Spring框架紧密结合用于提升Spring开发者体验的工具。同时它集成了大量常用的第三方库配置(例如Jackson, JDBC, Mongo, Redis, Mail等等),Spring Boot应用中这些第三方库几乎可以零配置的开箱即用(out-of-the-box),大部分的Spring Boot应用都只需要非常少量的配置代码,开发者能够更加专注于业务逻辑。
spring boot只是一个配置工具,整合工具,辅助工具 springmvc,mybatis等是框架,项目中实际运行的代码
Spring Boot只是承载者,辅助你简化项目搭建过程的。如果承载的是WEB项目,使用Spring MVC作为MVC框架,那么工作流程和Spring MVC的是完全一样的,因为这部分工作是Spring MVC做的而不是Spring Boot。
问题二 什么是自动配置
Spring 和 SpringMVC 的问题在于需要配置大量的参数。
Spring Boot会根据类路径中的jar包、类,为jar包里的类自动配置,这样可以极大的减少配置的数量。简单点说就是它会根据定义在classpath下的类,自动的给你生成一些Bean,并加载到Spring的Context中。自动配置充分的利用了spring 4.0的条件化配置特性,能够自动配置特定的Spring bean,用来启动某项特性(@Conditional检查配置文件是否存在某个属性,如存在就创建相关bean并注入到容器)。
条件化配置:
假设你希望一个或多个bean只有在某种特殊的情况下才需要被创建,比如,一个应用同时服务于中美用户,要在中美部署,有的服务在美国集群中需要提供,在中国集群中就不需要提供。在Spring 4之前,要实现这种级别的条件化配置是比较复杂的,但是,Spring 4引入了一个新的@Conditional注解可以有效的解决这类问题。
当@Conditional(ChinaEnvironmentCondition.class)条件的值为true的时候,该ServiceBean才会被创建,否则该bean就会被忽略。
@Conditional指定了一个条件。他的条件的实现是一个Java类——ChinaEnvironmentCondition,要实现以上功能就要定义ChinaEnvironmentCondition类,并继承Condition接口并重写其中的matches方法。
在上面的代码中,matches方法的内容比较简单,他通过给定的ConditionContext对象进而获取Environment对象,然后使用该对象检查环境中是否存在ENV_CN属性。如果存在该方法则直接返回true,反之返回false。当该方法返回true的时候,就符合了@Conditional指定的条件,那么ServiceBean就会被创建。反之,如果环境中没有这个属性,那么这个ServiceBean就不会被创建。
原理:
springboot文集下另一篇文章
问题三:什么是约定大于配置
如果有些值你没有配置的话,那程序会取一个默认值,换句话说,能取默认值的配置,就不需要配置了。这个默认值就是约定。
spring boot和maven的约定大于配置体现在哪些方面? 比如:
1、Spring Boot默认提供静态资源目录位置需置于classpath下,目录名需符合如下规则:
src/main/resources/
举例:我们可以在src/main/resources/目录下创建static,在该位置放置一个图片文件。启动程序后,尝试访问http://localhost:8080/D.jpg即可显示图片
2、spring boot默认的配置文件必须是,也只能是application或application-xxx命名的yml文件或者properties文件,且唯一
application.properties可能会出现中文乱码情况,所以推荐尽量使用yml文件
3、application.yml中默认属性:
a、数据库连接信息必须是以spring: datasource: 为前缀,如:
spring:
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://dev.yonyouccs.com:3001/icop-construct-busisubpack username: root
password: root
b、多环境配置。该属性可以根据运行环境自动读取不同的配置文件。例如将该属性定义为dev的话,Spring Boot会额外从application-dev.yml文件中读取该环境的配置。
spring:
profiles.active: dev
c、修改端口号、请求路径
server:
port: 8080 context-path: /xwj
问题四:什么是 Spring Boot Stater ?
starter是一种对依赖的synthesize(合成)
传统的做法:
在没有starter之前,假如我想要在Spring中使用jpa,那我可能需要做以下操作:
在Maven中引入使用的数据库的依赖(即JDBC的jar)
1. 引入jpa的依赖
2. 在xxx.xml中配置一些属性信息
3. 反复的调试直到可以正常运行
需要注意的是,这里操作在我们每次新建一个需要用到jpa的项目的时候都需要重复的做一次。也许你在第一次自己建立项目的时候是在Google上自己搜索了一番,花了半天时间解决掉了各种奇怪的问题之后,jpa终于能正常运行了。有些有经验的人会在OneNote上面把这次建立项目的过程给记录下来,包括操作的步骤以及需要用到的配置文件的内容,在下一次再创建jpa项目的时候,就不需要再次去Google了,只需要照着笔记来,之后再把所有的配置文件copy&paste就可以了。
像上面这样的操作也不算不行,事实上我们在没有starter之前都是这么干的,但是这样做有几个问题:
1. 如果过程比较繁琐,这样一步步操作会增加出错的可能性
2. 不停地copy&paste不符合Don’t repeat yourself精神
3. 在第一次配置的时候(尤其如果开发者比较小白),需要花费掉大量的时间
使用Spring Boot Starter提升效率
starter的主要目的就是为了解决上面的这些问题。
starter的理念:starter会把所有用到的依赖都给包含进来,避免了开发者自己去引入依赖所带来的麻烦。需要注意的是不同的starter是为了解决不同的依赖,所以它们内部的实现可能会有很大的差异,例如jpa的starter和Redis的starter可能实现就不一样。
starter的实现:虽然不同的starter实现起来各有差异,但是他们基本上都会使用到两个相同的内容:ConfigurationProperties和AutoConfiguration。因为Spring Boot坚信“约定大于配置”这一理念,所以我们使用ConfigurationProperties来保存我们的配置,并且这些配置都可以有一个默认值,即在我们没有主动覆写原始配置的情况下,默认值就会生效,这在很多情况下是非常有用的。除此之外,starter的ConfigurationProperties还使得所有的配置属性被聚集到一个文件中(一般在resources目录下的application.properties),这样我们就告别了Spring项目中XML地狱。
starter的整体逻辑:
上面的starter依赖的jar和我们自己手动配置的时候依赖的jar并没有什么不同,所以我们可以认为starter其实是把这一些繁琐的配置操作交给了自己,而把简单交给了用户。除了帮助用户去除了繁琐的构建操作,在“约定大于配置”的理念下,ConfigurationProperties还帮助用户减少了无谓的配置操作。并且因为 application.properties 文件的存在,即使需要自定义配置,所有的配置也只需要在一个文件中进行,使用起来非常方便。
问题五:如何构建 Spring Boot Stater ?
如果你想要自己创建一个starter,那么基本上包含以下几步
1. 创建一个starter项目
2. 创建一个ConfigurationProperties用于保存你的配置信息(如果你的项目不使用配置信息则可以跳过这一步,不过这种情况非常少见)
3. 创建一个AutoConfiguration,引用定义好的配置信息;在AutoConfiguration中实现所有starter应该完成的操作,并且把这个类加入spring.factories配置文件中进行声明
4. 打包项目,之后在一个SpringBoot项目中引入该项目依赖,然后就可以使用该starter了
举个栗子:
1. 首先新建一个Maven项目,设置 pom.xml 文件如下:
2. 创建proterties类来保存配置信息:
上面这个类就是定义了一个属性,其默认值是 http://www.baidu.com/,我们可以通过在 application.properties 中添加配置 http.url=https://www.zhihu.com 来覆盖参数的值。
3. 创建业务类:
这个业务类的操作非常简单,只包含了一个 url 属性和一个 getHtml 方法,用于获取一个网页的HTML数据,读者看看就懂了。
4. 创建AutoConfiguration
在上面的AutoConfiguration中我们实现了自己要求:在Spring的上下文中创建了一个HttpClient类的bean,并且我们把properties中的一个参数赋给了该bean。
关于@ConditionalOnMissingBean 这个注解,它的意思是在该bean不存在的情况下此方法才会执行,这个相当于开关的角色,更多关于开关系列的注解可以参考这里。
最后,我们在 resources 文件夹下新建目录 META-INF,在目录中新建 spring.factories 文件,并且在 spring.factories 中配置AutoConfiguration:
到此,我们的starter已经创建完毕了,使用Maven打包该项目。之后创建一个SpringBoot项目,在项目中添加我们之前打包的starter作为依赖,然后使用SringBoot来运行我们的starter,代码如下:
正常情况下此方法的执行会打印出url http://www.baidu.com/ 的HTML内容,之后我们在application.properties中加入配置:
http.url=https://www.zhihu.com/
再次运行程序,此时打印的结果应该是知乎首页的HTML了,证明properties中的数据确实被覆盖了。
https://www.nosuchfield.com/2017/10/15/Spring-Boot-Starters/
问题五:SpringBoot还提供了哪些starter
spring-boot-starter-web - Web 和 RESTful 应用程序
spring-boot-starter-test - 单元测试和集成测试
spring-boot-starter-jdbc - 传统的 JDBC
spring-boot-starter-security - 使用 SpringSecurity 进行身份验证和授权
spring-boot-starter-data-jpa - 带有 Hibeernate 的 Spring Data JPA
spring-boot-starter-log4j2
spring-boot-starter-data-redis:通过Spring Data Redis 、Jedis client使用Redis键值存储数据库
spring-boot-starter-batch:Spring Batch是一个轻量级的,完全面向Spring的批处理框架,可以应用于企业级大量的数据处理系统