扫码关注公众号:芋道源码

发送: 百事可乐
获取永久解锁本站全部文章的链接

《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 https://juejin.im/post/5aa22d1f51882555677e2492 「beyondlicg」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

背景

从Servlet技术到Spring和Spring MVC,开发Web应用变得越来越简捷。但是Spring和Spring MVC的众多配置有时却让人望而却步,相信有过Spring MVC开发经验的朋友能深刻体会到这一痛苦。因为即使是开发一个Hello-World的Web应用,都需要我们在pom文件中导入各种依赖,编写web.xml、spring.xml、springmvc.xml配置文件等。特别是需要导入大量的jar包依赖时,我们需要在网上查找各种jar包资源,各个jar间可能存在着各种依赖关系,这时候又得下载其依赖的jar包,有时候jar包间还存在着严格的版本要求,,所以当我们只是想开发一个Hello-World的超简单的Web应用时,却把极大部分的时间在花在了编写配置文件和导入jar包依赖上,极大地影响了我们的开发效率。所以为了简化Spring繁杂的配置,Spring Boot应运而生。正如Spring Boot的名称一样,一键启动,Spring Boot提供了自动配置功能,为我们提供了开箱即用的功能,使我们将重心放在业务逻辑的开发上。那么Spring Boot又是怎么简化Spring MVC的呢?Spring Boot和Spring、Spring MVC间又是怎样的关系呢?Spring Boot又有什么新特点呢?接下来,让我们走进Spring MVC 到Spring Boot的简化之路,或许你就能找到这些答案。

Spring vs Spring MVC vs Spring Boot

  • Spring Boot和Spring、Spring MVC不是竞争关系,Spring Boot使我们更加容易使用Spring和Spring MVC

Spring FrameWork

  • Spring FrameWork解决的核心问题是什么 Spring框架的最重要特性是依赖注入,所有的Spring模块的核心都是依赖注入(DI)或控制反转(IOC)。为什么很重要呢,因为当我们使用DI或IOC时,我们可以使应用得到解耦。我们来看一个简单的例子:

没有依赖注入的例子:

@RestController
public class WelcomeController {

private WelcomeService service = new WelcomeService();

@RequestMapping("/welcome")
public String welcome() {
return service.retrieveWelcomeMessage();
}
}

WelcomeService service = new WelcomeService(); 意味着WelcomeController类与WelcomeService类紧密结合在一起,耦合度高。

使用依赖注入的例子:

@Component
public class WelcomeService {
//Bla Bla Bla
}

@RestController
public class WelcomeController {

@Autowired
private WelcomeService service;

@RequestMapping("/welcome")
public String welcome() {
return service.retrieveWelcomeMessage();
}
}

依赖注入使世界看起来更简单,我们让Spring 框架做了辛勤的工作:
@Component:我们告诉Spring框架-嘿,这是一个你需要管理的bean
@Autowired:我们告诉Spring框架-嘿,找到这个特定类型的正确匹配并自动装入它

Spring 还能解决什么问题

1. 重复代码 Spring框架停止了依赖注入(DI)吗?没有,它在依赖注入(DI)的核心概念上开发了许多Spring模块:

  • Spring JDBC
  • Spring MVC
  • Spring AOP
  • Spring ORM
  • Spring Test
  • ... 考虑一下Spring JDBC,这些模块带来了新功能吗?并没有,我们完全可以使用Java代码完成这些工作。那么,它们给我们带来了什么?它们带来了简单的抽象,这些简单抽象的目的是:
  1. 减少样板代码/减少重复
  2. 促进解耦/增加单元可测性 例如:与传统的JDBC相比,我们使用Spring JDBC需要编写的代码减少了许多。

2. 与其他框架良好的集成 Spring框架并不尝试去解决已经解决了的问题,它所做的一切就是提供与提供出色解决方案的框架的完美集成。

  • Hibernate
  • IBatis
  • JUnit
  • ...

Spring MVC

  • Spring MVC框架解决的核心问题是什么 Spring MVC框架提供了开发Web应用的分离方式。通过DispatcherServlet、ModelAndView、View Resolver等简单概念,是Web应用开发变得更加简单。

为什么需要Spring Boot

基于Spring的应用程序有很多配置。当我们使用Spring MVC时,我们需要配置组件扫描,调度器servlet,视图解析器等:

视图解析器配置:
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>

<mvc:resources mapping="/webjars/**" location="/webjars/"/>

前端调度器的典型配置:
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/todo-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

当我们使用Hibernate / JPA时,我们需要配置一个数据源,一个实体管理器工厂,一个事务管理器以及许多其他事物:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${db.driver}" />
<property name="jdbcUrl" value="${db.url}" />
<property name="user" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>

<jdbc:initialize-database data-source="dataSource">
<jdbc:script location="classpath:config/schema.sql" />
<jdbc:script location="classpath:config/data.sql" />
</jdbc:initialize-database>

<bean
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
id="entityManagerFactory">
<property name="persistenceUnitName" value="hsql_pu" />
<property name="dataSource" ref="dataSource" />
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSource" />
</bean>

<tx:annotation-driven transaction-manager="transactionManager"/>

Spring Boot解决的问题

1. Spring Boot 自动配置 Spring引入了新的思维过程:我们可以变得更加智能些吗?当一个spring mvc jar包被添加到应用程序时,我们是否可以自动配置一些bean?

  1. 当Hibernate jar包在类路径时,自动配置数据源怎样?
  2. 当Spring MVC jar包在类路径时,自动配置Dispatcher Servlet怎样?
  • Spring Boot查看ClASSPATH上对于本应用程序需要编写配置的框架,基于这些,Spring Boot提供了这些框架的基本配置-这就是自动配置。

2. Spring Boot Starter Projects 假设我们想开发一个Web应用程序。首先,我们需要确定我们想要使用的框架,使用哪个版本的框架以及如何将它们连接在一起。所有Web应用程序都有类似的需求 下面列出的是我们在Spring MVC中使用的一些依赖关系。这些包括Spring MVC,Jackson Databind(用于数据绑定),Hibernate-Validator(用于使用Java验证API的服务器端验证)和Log4j(用于日志记录)。在创建时,我们必须选择所有这些框架的兼容版本:

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.2.RELEASE</version>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>

<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.0.2.Final</version>
</dependency>

<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>

  • 什么是Starter

Starter是一套方便的依赖描述符,可以包含在应用程序中。
你可以获得所需的所有Spring及相关技术的一站式服务,而无需搜索示例代码并复制依赖描述符的粘贴负载。
例如,如果你想开始使用Spring和JPA来访问数据库,只需在你的项目中包含spring-boot-starter-data-jpa依赖项就好。

我们来看Starter的一个示例 - Spring-Boot-Starter-Web

Spring-Boot-Starter-Web依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

以下屏幕截图显示了添加到我们的应用程序中的不同依赖关系:

img

任何典型的Web应用程序都会使用所有这些依赖项.Spring Boot Starter Web预先打包了这些。作为开发人员,我们不需要担心这些依赖关系或兼容版本。

3. Spring Boot Starter项目选项 正如Spring Boot Starter Web一样,Starter项目帮助我们快速入门开发特定类型的应用程序:

  • spring-boot-starter-web-services - SOAP Web服务
  • spring-boot-starter-web - Web和RESTful应用程序
  • spring-boot-starter-test - 单元测试和集成测试
  • spring-boot-starter-data-jpa - 带有Hibernate的Spring Data JPA
  • spring-boot-starter-cache - 启用Spring Framework的缓存支持
  • ...

什么是Spring Boot 自动配置

前面已经初步介绍过,在这里详细介绍一下。 当我们启动Spring Boot应用程序时,我们可以在日志中看到一些重要的消息。

Mapping servlet: 'dispatcherServlet' to [/]

Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)

Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]

上面的日志语句显示了Spring Boot Auto Configuration的行为。 一当我们在应用中添加了Spring Boot Starter Web依赖,Spring Boot AutoConfiguration就会发现Spring MVC在类路径下,它会自动配置dispatcherServlet,一个默认的错误页面和webjars。 如果你添加了Spring Boot DataJPA Starter依赖,Spring Boot AutoConfiguration会自动配置数据源(datasource)和实体管理器(Entity Manager)

Spring Boot Auto Configuration在哪里实现

所有的自动配置逻辑都在spring-boot-autoconfigure.jar中实现。mvc、data和其他框架的所有自动配置逻辑都存在与一个jar包中。

img

spring-boot-autoconfigure.jar中重要的文件是/META-INF/spring.factories,该文件;列出了在EnableAutoConfiguration key下启动的所有自动配置类。下面列出一些重要的配置类:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\

查看自动配置

打开调试日志 在application.properties打开调试日志:

logging.level.org.springframework: DEBUG

当启动程序时,会打印自动配置日志信息

总结

Spring Boot的出现本身就是为了减低Web开发的门槛,使开发人员能够专注于业务开发,而不需浪费时间在业务开发之外,至此Spring MVC到Spring Boot的简化之路到此结束。

文章目录
  1. 1. 背景
  2. 2. Spring vs Spring MVC vs Spring Boot
    1. 2.1. Spring FrameWork
    2. 2.2. Spring 还能解决什么问题
    3. 2.3. Spring MVC
    4. 2.4. 为什么需要Spring Boot
  3. 3. 什么是Spring Boot 自动配置
    1. 3.1. Spring Boot Auto Configuration在哪里实现
    2. 3.2. 查看自动配置
  4. 4. 总结