深度解析springboot自动配置原理及实战

  • A+
所属分类:Spring
深度解析springboot自动配置原理及实战

在微服务发展如火如荼的今天,无论是互联网公司还是传统IT业,都在向着微服务时代迅速的靠拢。随着各行业业务的不断发展,软件系统传统的单一架构已经无法支撑业务的迅猛发展,在传统架构发展当中,将系统的所有业务都冗余进一个系统中,无疑会造成各种各样的问题。如:可扩展性降低、可维护性差、开发效率低等等。为了改善这个状况。那么,就需要对单一架构进行拆分,根据业务进行划分或根据模块进行划分,将各个业务模块划分为微服务,从而使整个系统改变为分布式架构。springboot具有得天独厚的微服务开发优势。

为什么使用springboot,优势有哪些?

  • 开箱即用,不需要太多的配置,降低开发成本(自动配置)
  • 一键打包,一键启动(提供的jar文件直接运行系统)
  • 提供通用的非功能性功能(内嵌服务器、系统安全、系统监控等)
  • 一站式服务、集成众多优秀开源框架start

上面描述了springboot的使用场景以及使用的原因,接下来就让我们一层一层解开springboot的神秘面纱。

本系列文章会从三个方面来逐一剖析springboot的核心原理

  1. springboot自动配置的实现原理
  2. springboot启动过程
  3. 定义自己的start

本文先来讲一讲Springboot自动配置的实现原理

自动配置,顾名思义就是不需要开发者自己去配置应用程序,而是只要满足springboot实现自动配置的条件即可。具体来说就是Springboot根据开发者添加的jar包依赖项来自动配置springboot程序的。

实现springboot自动配置需要了解以下几个重要的注解

@SpringBootApplication 它是一个复合注解,可以使用该注解启动三个功能

  • @EnableAutoConfiguration : 启动springboot的自动配置
  • @ComponentScan:在应用程序所在的包上启用扫描
  • @Configuration:配置类注解(JavaConfig形式)
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication //与@Configuration相同@EnableAutoConfiguration @ComponentScan 
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

上述代码是springboot的启动主类,其实它也是一个配置类
注:springboot启动主类必须放在项目的根目录下,以便@ComponentScan注解去扫描项目内所有注解的Bean成员,如果未放在根目录下,则项目中的Bean无法被扫描使用。

深度解析springboot自动配置原理及实战

@Configuration注解

@Configuration用户定义配置类,其实是以JavaConfig形式存在的配置项,可替换为XML文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。

@Configuration标注在类上,相当于把该类作为spring的xml文件中的,作用于spring容器(应用上下文)

package com.example.demo.config;

import org.springframework.context.annotation.Configuration;
/**
 * @Description spring配置
 * @Author mengxi.zh
 * @date 2019-06-04 18:19
 * @Copyright 2019 mengxi.blog All right reserved.
 */
@Configuration
public class myspringboot {

}

相当于:





@ComponentScan

@ComponentScan 注解用于扫描该项目包下的所有spring注解,将该包下的实例bean(诸如:@Component,@Controller,@Service,@Repository等注解修饰的Bean)注入spring容器中。之前在开发过程中使用XML形式配置spring容器时,就使用过类似的扫描配置,@ComponentScan注解就相当于XML配置文件中的标签。根据指定的配置base-package属性可指定自动扫描项目包的路径,相信大家一定不陌生。

 

@EnableAutoConfiguration

@EnableAutoConfiguration注解 翻译过来就是开启自动配置,是springboot自动配置最核心的注解。

深度解析springboot自动配置原理及实战

@EnableAutoConfiguration注解导入了一个比较重要的Java类,即AutoConfigurationImportSelector,从字面理解这个类就是 ”选择自动导入的配置信息“,其中这个类中的selectImports()方法就是去获取需要自动配置的候选类。我们来看一下这个方法。

深度解析springboot自动配置原理及实战
深度解析springboot自动配置原理及实战

从上述方法中可以看到通过getCandidateConfigurations方法获取候选配置类,这个方法其实就是通过spring的工具类SpringFactoriesLoader.loadFactoryNames去扫描所有具有META-INF/spring.factories的jar包。

深度解析springboot自动配置原理及实战
深度解析springboot自动配置原理及实战

spring-boot-autoconfigure的jar包下就有spring.factories文件,查看文件内容。

深度解析springboot自动配置原理及实战

可以发现这个配置文件中的内容是以key-value形式存在的,key为类的全路径,对应的value类列表名,value以”逗号隔开“。

这个@EnableAutoConfiguration注解通过@SpringBootApplication被间接的标记在了Spring Boot的启动类上。在SpringApplication.run(…)的内部就会执行selectImports()方法,找到所有JavaConfig自动配置类的全限定名对应的class,然后将所有自动配置类加载到Spring容器中。

条件注解

然而并不是所有找到value的类路径全都会被加载至spring容器中,springboot自动配置以条件注解方式进行动态的Bean实例注入。

常见的条件注解:

Conditions描述
@ConditionalOnBean在存在某个bean的时候
@ConditionalOnMissingBean不存在某个bean的时候
@ConditionalOnClass当前classpath可以找到某个类型的类时
@ConditionalOnMissingClass当前classpath不可以找到某个类型的类时
@ConditionalOnResource当前classpath是否存在某个资源文件
@ConditionalOnProperty当前jvm是否包含某个系统属性为某个值
@ConditionalOnWebApplication当前spring context是否是web应用程序

每个autoConfigure自动配置类都会有一定得条件约束,只有满足约束条件才可以被spring容器加载成功。

深度解析springboot自动配置原理及实战

使用RedisAutoConfiguration自动配置类来说明,配置类上有个@ConditionalOnClass注解,该注解的意思是当前classpath存在某个类型的类才会被spring容器加载成功,也就是说classpath下如果有RedisOperations这个类时才会被spring容器加载。

再来说一说全局的配置变量,还是以上述redis加载为例,可以看到有一个@EnableConfigurationProperties注解,这个注解的含义是导入已经绑定配置文件的bean至spring容器中,此处将RedisProperties该文件的配置属性导入至spring容器中。下面我们看一下RedisProperties这个文件。

深度解析springboot自动配置原理及实战

@ConfigurationProperties 这个注解的含义就是 绑定配置信息到Bean上。此处的前缀为"spring.redis",这里就是我们经常使用springboot的全局配置文件application.yml或application.properties文件中配置的各个应用信息,最终落地到对应的xxxProperties的Bean上。然后上述@EnableConfigurationProperties注解则将xxxProperties.class的信息自动导入至spring容器中。

用一张大佬的图表示下springboot自动配置的流程图:

深度解析springboot自动配置原理及实战

总结

最后总结一下springboot自动配置的原理实现

1、springboot主程序执行时会通过@EnableAutoConfiguration注解找到META-INF/spring.factories文件中的自动配置类。

2、自动配置类一般可以认为是以AutoConfiguration为结尾的JavaConfig形式的配置文件类,而如果需要这些配置文件加载至Spring容器中,必须满足以@Condition为注解修饰的条件。
3、自动配置类可以通过以properties文件结尾的类中取得全局配置文件中的配置,比如:spring.redis等,而以properties文件结尾的类则是通过@ConfigurationProperties注解与全局配置文件中的配置属性进行绑定的。

4、@EnableConfigurationProperties注解将以properties为结尾的类信息自动导入至spring容器中并完成所有组件的自动配置。

  • 我的微信
  • 加好友一起交流!
  • weinxin
  • 微信公众号
  • 关注公众号获取分享资源!
  • weinxin

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: