刚关注的朋友,可以回顾前两篇文章:

上篇文章总结了《深入实践Spring Boot》的第二部分,本篇文章总结第三部分,也是最后一部分。这部分主要讲解核心技术的源代码分析,因为篇幅和能力原因,分析的不会太详细,后续深入研究后再专门写文章。希望大家能从「阅读笔记」3篇文章中,对Spring Boot提供的功能有所了解,在项目中进行实践,不断从繁琐重复的开发中解放出来。

我也是最近刚开始了解Spring Boot,计划今年在项目中实践,到时会总结实践过程中的一些问题和经验,分享给大家。想一起学习、实践、交流的朋友,可以扫描文章下方的二维码,关注我的个人公众号,感谢大家。

本篇主要从以下几个方面总结:

  • Spring Boot自动配置实现原理;
  • Spring Boot数据访问实现原理;
  • 微服务核心技术实现原理;

题外话

春节假期很快过去了,明天就要上班了,相信大家还是意犹未尽,没吃够、没玩够、没和家人待够。今年因为个人原因,没有回家过年,心理最牵挂的还是爷爷奶奶,他们都80多了,希望她们身体健康,开开心心地度过生命最后的旅程。

不管怎样,大家要切换频道了,回归到正常的工作中,好好努力,一起期待明年和家人更好的团聚。

Spring Boot自动配置实现原理

使用Spring Boot创建一个简单的Web项目很简洁,不需要太多配置,编写一个简单的主程序就行:

@SpringBootApplication
public class ConfigApplication{
public static void main(String[] args) {
SpringApplication.run(ConfigApplication.class, args);
}
主程序分析

首先分析下run方法(省略不关键的部分代码):

public ConfigurableApplicationContext run(String... args) {

        ConfigurableApplicationContext context = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.started();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
analyzers = new FailureAnalyzers(context);
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
listeners.finished(context, null);
return context;
}
catch (Throwable ex) {
handleRunFailure(context, listeners, analyzers, ex);
throw new IllegalStateException(ex);
}
}

它首先开启一个SpringApplicationRunListeners监听器,然后创建一个应用上下文ConfigurableApplicationContext,通过这个上下文加载应用所需的类和各种环境配置等。

一个应用能够正常运行起来,需要一些环境变量、各种资源和一些相关配置等,下面看下createApplicationContext方法会加载应用定义的和需要的类及各种资源。

自动配置

所有的自动配置都是从注解@SpringBootApplication引入的,它其实又包含了@Configuration、@EnableAutoConfiguration和@ComponentScan,其中,@EnableAutoConfiguration就是启用自动配置的,并将导入一些自动配置的类定义。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
Class<?>[] exclude() default {};
String[] excludeName() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackages"
)
String[] scanBasePackages() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackageClasses"
)
Class<?>[] scanBasePackageClasses() default {};
}

EnableAutoConfiguration最终会导入一个自动配置的类列表,列表中的自动配置类很多,这些配置类中大都将被导入,并处于备用状态,当项目中引入了相关的包时,相关的功能将被启用。

例如在项目的maven配置中配置了Redis的引用,Redis的默认配置项将被启用,首先会读取项目中的配置,只有项目中没有相关配置才启用配置的默认值,下面代码是Redis的自动配置,如果配置文件中没设置,会使用下面默认设置。

@ConfigurationProperties(
prefix = "spring.redis"
)
public class RedisProperties {
private int database = 0;
private String host = "localhost";
private String password;
private int port = 6379;
private int timeout;
private RedisProperties.Pool pool;
private RedisProperties.Sentinel sentinel;
private RedisProperties.Cluster cluster; public RedisProperties() {
}

通过自动配置,就不用重复定义配置项名称了,覆盖约定的配置项即可。可通过查看各个Properties类,查看有哪些配置项。

Spring Boot数据访问实现原理

要使用数据库,首先必须与数据库服务器建立连接。对于关系型数据库,Spring Boot 连接数据源一般都采用JDBC的方式来实现。其他类型的数据库使用各自独立的方式来建立连接。

数据源类型和驱动

JDBC连接数据源必须指定数据源类型和数据库驱动程序,数据源主要有4中:

  • 使用java.sql.DriverManager类;
  • 使用实现了javax.sql.DataSource接口的子类,DataSource接口由驱动程序供应商实现,主要有3类实现、基本实现、连接池实现,分布式事务实现 ;
  • DBCP连接池,Apache 软件基金组织下的开源连接池实现,Tomcat 的连接池正是采用该连接池来实现的;
  • C3P0连接池;

Spring Boot 默认使用org.apache.tomcat.jdbc.pool.DataSource,它使用第2种方式,实现了javax.sql.DataSource接口。数据源的类型可以通过配置更改。

另外,Spring Boot 默认几乎支持现有的所有数据库。

数据存取功能实现

与数据库建立连接后,就可以对数据库执行一些存取操作,对数据库实现管理的功能。数据存取操作大体上包含两方面的内容,即实体建模和持久化。

不管是关系型数据库,还是NoSQL数据库,都遵循这一设计规范。实体建模即将Java的普通对象和关系映射为数据库表机器相关的关系,在Spring Boot中,主要是通过注解实现。

关系型数据库都使用了JPA的一套标准,它结合使用Hibernate实现了实体的持久化。后续的数据库管理设计都遵循了JPA这一个标准规范,提供相同的访问数据库的API。

微服务核心技术实现原理

Spring Cloud是基于对Netfix开源组件进一步封装的一套云应用开发工具,可以用来开发各种微服务应用。

配置服务实现

前一篇文章说到,配置管理的在线更新功能使用事件总线,即spring-cloud-bus来发布状态变化,并使用分布式消息来发布更新事件,分布式消息最终使用RabbitMQ来实现消息收发。

再来回顾下在线更新流程:

  • 更新Git仓库的配置文件;
  • 以POST指令出发更新请求;
  • 配置管理服务器从Git仓库中读取配置文件,并将配置文件分发给各个客户端,同时在RabbitMQ中发布一个更新消息;
  • 客户端订阅RabbitMQ消息,收到消息后执行更新;

配置管理服务器中的消息分发是从spring-cloud-bus中调用spring-cloud-stream组件实现的,而spring-cloud-stream使用RabbitMQ实现了分布式消息分发。具体实现就不说了,使用过RabbitMQ的很好理解。

发现服务和负载均衡

客户端执行注册使用计划任务的方式来实现,而客户端从发现服务器中更新其他在线的客户端列表,也使用了一个定时任务来管理。

当一个应用启用发现服务的功能之后,会默认启用Ribbon的负载均衡服务。Ribbon通过发现服务获取在线的客户端,为具有多个实例的客户端建立起负载均衡管理机制。

分布式消息实现

使用spirng-cloud-stream可以非常简单地使用RabbitMQ的异步消息,Spring Cloud的配置管理中的分布式消息分发也是通过调用spring-cloud-stream组件来实现的。

下面以消息生产者和消费者的实现说明分布式消息实现

消息生产者:

@EnableBinding(Source.class)
@RestController
@SpringBootApplication
public class SenderApplication {
@Autowired
@Output(Source.OUTPUT)
private MessageChannel channel; @RequestMapping(method = RequestMethod.POST, path = "/send")
public void write (@RequestBody Map<String, Object> msg){
channel.send(MessageBuilder.withPayload(msg).build());
} public static void main(String[] args) {
SpringApplication.run(SenderApplication.class, args);
}
}

消息消费者:

@EnableBinding(Sink.class)
@IntegrationComponentScan
@MessageEndpoint
@SpringBootApplication
public class ReceiverApplication {
@ServiceActivator(inputChannel=Sink.INPUT)
public void accept(Map<String, Object> msg){
System.out.println(msg.get("msg").toString() + ":" + msg.get("name"));
} public static void main(String[] args) {
SpringApplication.run(ReceiverApplication.class, args);
}
}

从上面的分析可以看到,Spring Boot及其一些相关组件,已经尽量把一些可以实现和做到的功能,都帮我们实现了。 虽然使用Spring Boot及其相关组件看起来非常简单,但实际上可以实现无比强大的功能,这就是Spring Boot 及其组件的神奇所在。

《深入实践Spring Boot》阅读笔记之三:核心技术源代码分析的更多相关文章

  1. spring boot整合jsp的那些坑(spring boot 学习笔记之三)

    Spring Boot 整合 Jsp 步骤: 1.新建一个spring boot项目 2.修改pom文件 <dependency>            <groupId>or ...

  2. 《深入实践Spring Boot》阅读笔记之一:基础应用开发

    上上篇「1718总结与计划」中提到,18年要对部分项目拆分,进行服务化,并对代码进行重构.公司技术委员会也推荐使用spring boot,之前在各个技术网站中也了解过,它可以大大简化spring配置和 ...

  3. 《深入实践Spring Boot》阅读笔记之二:分布式应用开发

    上篇文章总结了<深入实践Spring Boot>的第一部分,这篇文章介绍第二部分:分布式应用开发,以及怎么构建一个高性能的服务平台. 主要从以下几个方面总结: Spring Boot SS ...

  4. Spring Boot学习笔记2——基本使用之最佳实践[z]

    前言 在上一篇文章Spring Boot 学习笔记1——初体验之3分钟启动你的Web应用已经对Spring Boot的基本体系与基本使用进行了学习,本文主要目的是更加进一步的来说明对于Spring B ...

  5. Spring Boot 学习笔记(六) 整合 RESTful 参数传递

    Spring Boot 学习笔记 源码地址 Spring Boot 学习笔记(一) hello world Spring Boot 学习笔记(二) 整合 log4j2 Spring Boot 学习笔记 ...

  6. Spring Boot 揭秘与实战 源码分析 - 工作原理剖析

    文章目录 1. EnableAutoConfiguration 帮助我们做了什么 2. 配置参数类 – FreeMarkerProperties 3. 自动配置类 – FreeMarkerAutoCo ...

  7. Spring Boot 启动(一) SpringApplication 分析

    Spring Boot 启动(一) SpringApplication 分析 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html ...

  8. Spring Boot 揭秘与实战 源码分析 - 开箱即用,内藏玄机

    文章目录 1. 开箱即用,内藏玄机 2. 总结 3. 源代码 Spring Boot提供了很多”开箱即用“的依赖模块,那么,Spring Boot 如何巧妙的做到开箱即用,自动配置的呢? 开箱即用,内 ...

  9. Spring Boot自动装配原理源码分析

    1.环境准备 使用IDEA Spring Initializr快速创建一个Spring Boot项目 添加一个Controller类 @RestController public class Hell ...

随机推荐

  1. 2018 年 3 月 iOS架构师 面试总结

    序言: 今年2月中下旬因为个人原因,换了一份工作,3月初期间面试了有3,4家,基本都是D轮或者刚刚上市的公司,也有上榜的BAT,也从他们的面试笔试中看到了自己的一些不足,于是就想写出来和大家分享一下, ...

  2. SpringMVC【参数绑定、数据回显、文件上传】

    前言 本文主要讲解的知识点如下: 参数绑定 数据回显 文件上传 参数绑定 我们在Controller使用方法参数接收值,就是把web端的值给接收到Controller中处理,这个过程就叫做参数绑定.. ...

  3. 负载均衡,会话保持,session同步(转)

    转自:http://bbs.linuxtone.org/thread-18212-1-1.html 一,什么负载均衡一个新网站是不要做负载均衡的,因为访问量不大,流量也不大,所以没有必要搞这些东西.但 ...

  4. 特殊权限chattr的用法

    1,只能对文件进行追加操作: [root@localhost tmp]# cat yum.log 22222222222222[root@localhost tmp]# chattr +a yum.l ...

  5. Symbol(第6种基本数据类型)

    构造函数 不能使用构造函数,只能当成平常的方法使用 new Symbol()//VM372:1 Uncaught TypeError: Symbol is not a constructor 参数:不 ...

  6. python安装第三方库

    在编写爬虫程序时发现unsolved import 一时不解,以为是ide出问题了,其实是没有安装第三方库导致的. 于是到https://pypi.python.org/pypi/requests/去 ...

  7. 笔记:I/O流-文件操作

    Java库中使用 Path 和 Files 类封装了在用户机器上处理文件系统所需要的所有功能,可以使用Paths来获取一个具体的Path对象,来表示具体的路径. 路径 Path表示的是一个目录名序列, ...

  8. linux --> Linux 的启动流程

    Linux 的启动流程 操作系统接管硬件以后发生的事情,也就是操作系统的启动流程. 因为在BIOS阶段,计算机的行为基本上被写死了,程序员可以做的事情并不多:但一旦进入操作系统,程序员几乎可以定制所有 ...

  9. 设计模式 --> (15)职责链模式

    职责链模式 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. 示例 考虑员工要求加薪.公司的管理者一共有 ...

  10. 设计模式 --> (4)建造者模式

    建造者(Builder)模式 建造者(Builder)模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 建造者模式包含一个抽象的Builder类,还有它的若干子类——Co ...