SpringBoot的核心就是自动配置,自动配置是基于条件判断配置Bean

自动配置的源码在spring-boot-autoconfigure-2.2.13.RELEASE

SpringBoot运行原理

先看@SpringBootApplication

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.springframework.boot.autoconfigure;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.core.annotation.AliasFor;@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {@Filter(type = FilterType.CUSTOM,classes = {TypeExcludeFilter.class}
), @Filter(type = FilterType.CUSTOM,classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {@AliasFor(annotation = EnableAutoConfiguration.class)Class<?>[] exclude() default {};@AliasFor(annotation = EnableAutoConfiguration.class)String[] excludeName() default {};@AliasFor(annotation = ComponentScan.class,attribute = "basePackages")String[] scanBasePackages() default {};@AliasFor(annotation = ComponentScan.class,attribute = "basePackageClasses")Class<?>[] scanBasePackageClasses() default {};@AliasFor(annotation = Configuration.class)boolean proxyBeanMethods() default true;
}

主要关注的几个注解如下

@SpringBootConfiguration:标记当前类为配置类

@EnableAutoConfiguration:开启自动配置

@ComponentScan:扫描主类所在的同级包以及下级包里的Bean

关键是@EnableAutoConfiguration

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.springframework.boot.autoconfigure;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";Class<?>[] exclude() default {};String[] excludeName() default {};
}

最关键的要属@Import(EnableAutoConfigurationImportSelector.class),借助EnableAutoConfigurationImportSelector,@EnableAutoConfiguration可以帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器:通过@Import(AutoConfigurationImportSelector.class)导入的配置功能,

AutoConfigurationImportSelector中的方法getCandidateConfigurations,得到待配置的class的类名集合,这个集合就是所有需要进行自动配置的类,而是否配置的关键在于META-INF/spring.factories文件中是否存在该配置信息

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");return configurations;}

打开,如下图可以看到所有需要配置的类全路径都在文件中,每行一个配置,多个类名逗号分隔,而\表示忽略换行

样例讲解

以SpringApplicationAdminJmxAutoConfiguration类来看其主要构成部分

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.springframework.boot.autoconfigure.admin;import java.util.Iterator;
import javax.management.MalformedObjectNameException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.jmx.export.MBeanExporter;@Configuration(proxyBeanMethods = false
)
@AutoConfigureAfter({JmxAutoConfiguration.class})
@ConditionalOnProperty(prefix = "spring.application.admin",value = {"enabled"},havingValue = "true",matchIfMissing = false
)
public class SpringApplicationAdminJmxAutoConfiguration {private static final String JMX_NAME_PROPERTY = "spring.application.admin.jmx-name";private static final String DEFAULT_JMX_NAME = "org.springframework.boot:type=Admin,name=SpringApplication";public SpringApplicationAdminJmxAutoConfiguration() {}@Bean@ConditionalOnMissingBeanpublic SpringApplicationAdminMXBeanRegistrar springApplicationAdminRegistrar(ObjectProvider<MBeanExporter> mbeanExporters, Environment environment) throws MalformedObjectNameException {String jmxName = environment.getProperty("spring.application.admin.jmx-name", "org.springframework.boot:type=Admin,name=SpringApplication");if (mbeanExporters != null) {Iterator var4 = mbeanExporters.iterator();while(var4.hasNext()) {MBeanExporter mbeanExporter = (MBeanExporter)var4.next();mbeanExporter.addExcludedBean(jmxName);}}return new SpringApplicationAdminMXBeanRegistrar(jmxName);}
}

都能看到各种各样的条件判断注解,满足条件时就加载这个Bean并实例化

手动实现自动配置的demo

项目目录

1.XiaoServer文件

package com.xiao.configure;/*** 需要被实例化的服务类* @author xiaoss* @date 2021年11月03日 14:35*/
public class XiaoServer {private String name;public String sayServerName(){return "I'm " + name + "! ";}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

2.XiaoServerProperties文件

package com.xiao.configure;import org.springframework.boot.context.properties.ConfigurationProperties;/*** 配置信息属性类* @author xiaoss* @date 2021年11月03日 14:55*/
@ConfigurationProperties(prefix = "xiao")
public class XiaoServerProperties {private static final String NAME = "xiao_server0";private String name = NAME;public String getName() {return name;}public void setName(String name) {this.name = name;}}

3.XiaoServiceAutoConfiguration文件

package com.xiao.configure;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** 自动配置类* @author xiaoss* @date 2021年11月03日 14:58* 根据条件判断是否要自动配置,创建Bean*/
@Configuration
@EnableConfigurationProperties(XiaoServerProperties.class)
@ConditionalOnClass(XiaoServer.class)//判断XiaoServer这个类在类路径中是否存在
@ConditionalOnProperty(prefix = "xiao",value = "enabled",matchIfMissing = true)
public class XiaoServiceAutoConfiguration {@Autowiredprivate XiaoServerProperties mistraServiceProperties;@Bean(name = "xiaoServer")@ConditionalOnMissingBean(XiaoServer.class)//当容器中没有这个Bean时(XiaoServer)就自动配置这个Bean,Bean的参数来自于XiaoServerPropertiespublic XiaoServer mistraService(){XiaoServer mistraService = new XiaoServer();mistraService.setName(mistraServiceProperties.getName());return mistraService;}}

4.SpringbootAutoconfigureApplication文件

package com.xiao;import com.xiao.configure.XiaoServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Date;@SpringBootApplication
@RestController
public class SpringbootAutoconfigureApplication {@Autowiredprivate XiaoServer xiaoService;public static void main(String[] args) {SpringApplication.run(SpringbootAutoconfigureApplication.class, args);}@RequestMapping("/")public Object index(){return "helll demo "+xiaoService.getName()+" "+new Date();}
}

5.spring.factories

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.xiao.configure.XiaoServiceAutoConfiguration

6.application.properties

xiao.name=test service

7.pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><!--<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.6</version><relativePath/> &lt;!&ndash; lookup parent from repository &ndash;&gt;</parent>--><groupId>com.xiao</groupId><artifactId>springboot-autoconfigure</artifactId><version>0.0.1-SNAPSHOT</version><name>springboot-autoconfigure</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.5.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.5.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>2.2.13.RELEASE</version><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

运行结果:

总结:

一、什么是springBoot自动配置

SSM项目创建一次,需要写大量的配置文件,而springboot只需要写少量的配置,其他的都交给自动配置,按条件创建bean

二、springboot自动配置是怎么运行的

  1. 当SpringBoot项目启动时,会先去扫描所有jar包下的META-INF/spring.factories配置文件

2.通过读取spring.factories配置文件得到所有自动配置类的全限定类名,并将这些自动配置类全部注入到IOC容器

3.那么多类是全部都注入进去?当然不是,在这些配置类中都有条件注解,这些条件注解会去判断是否要导入

4.经过以上步骤,就实现了自动配置的过程,当然详细的实现细节肯定不会这么简单

SpringBoot自动配置的原理及实现相关推荐

  1. SpringBoot自动配置Redis原理

    SpringBoot自动配置Redis原理 目录 SpringBoot自动配置Redis原理 一.SpringBoot自动配置Redis原理 一.自动配置redis RedisAutoConfigur ...

  2. springboot自动配置的原理_SpringBoot实战:详解SpringBoot自动配置原理

    SpringBoot 自动配置主要通过 @EnableAutoConfiguration, @Conditional, @EnableConfigurationProperties 或者 @Confi ...

  3. springboot自动配置的原理_SpringBoot自动配置原理

    SpringBoot的启动入口就是一个非常简单的run方法,这个run方法会加载一个应用所需要的所有资源和配置,最后启动应用. 通过查看run方法的源码,我们发现,run方法首先启动了一个监听器,然后 ...

  4. SpringBoot自动配置MVC原理

    SpringBoot自动配置了MVC究竟都配置了那些东西,该如何自定义呢? 摸了!直接看官方文档(其实我也看不大懂英语) https://docs.spring.io/spring-boot/docs ...

  5. 聊一聊 SpringBoot 自动配置的原理

    解析思路 我们建立好一个SpringBoot的工程后,我们将从启动类,SpringBootApplication开始进行探究. 开始解析 首先我们建立一个 Springboot的工程.找到启动类,我们 ...

  6. SpringBoot自动配置实现原理及源码解析(2.3.x)

    约定优于配置,这是SpringBoot中的一个很重要特性,此特性让我们可以在几秒中之内完成一个项目的搭建,无需任何配置,本文就通过深入源码的方式来探索下自动配置的实现过程 为什么要自动配置 手动配置很 ...

  7. 笑死,面试官又问我SpringBoot自动配置原理

    面试官:好久没见,甚是想念.今天来聊聊SpringBoot的自动配置吧? 候选者:嗯,SpringBoot的自动配置我觉得是SpringBoot很重要的"特性"了.众所周知,Spr ...

  8. 这样讲 SpringBoot 自动配置原理,你应该能明白了吧

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:你在我家门口 juejin.im/post/5ce5effb ...

  9. 今天,我们来详细的聊一聊SpringBoot自动配置原理,学了这么久,你学废了吗?

    SpringBoot是我们经常使用的框架,那么你能不能针对SpringBoot实现自动配置做一个详细的介绍.如果可以的话,能不能画一下实现自动配置的流程图.牵扯到哪些关键类,以及哪些关键点. 下面我们 ...

最新文章

  1. 恶意软件盯上了加密货币,两家以色列公司受到攻击
  2. Nature重磅综述|关于RNA-seq,你想知道的都在这(续)
  3. 一像素约束(选中所需约束,切换到类处,选择此类,运行时就是0.5的约束)
  4. Spring的bean管理(注解注入属性)
  5. 创建一个简单的MFC程序
  6. TCP/IP常见攻击手段
  7. python turtle菜鸟教程_【读书】Django教程(菜鸟教程)
  8. Comparing Mongo DB and Couch DB
  9. 输出纹波和纹波电流测试规范分享
  10. 【知识图谱问答】DBpedia介绍
  11. 洪水填充算法_洪水填充算法分析
  12. ssm+Vue计算机毕业设计学科竞赛赛场安排系统(程序+LW文档)
  13. web前端入门到实战:CSS颜色、背景和剪切
  14. html网页设计大赛作品介绍,HTML网页设计大赛--赛出风采
  15. 家庭光纤宽带有必要升级千兆双频路由器吗?
  16. webdav服务器文件大小限制,WebDAV服务器
  17. 【牛客网】树根与星际密码
  18. h5网页服务器选择,h5制作选择虚拟主机还是服务器
  19. linux修改u盘卷标,如何在Linux下格式化U盘以及修改卷标
  20. 使用Deal.II过程

热门文章

  1. wake_lock_timeout的使用方法【转】
  2. 深入理解Java中为什么内部类可以访问外部类的成员
  3. 数据仓库的未来 MariaDB ColumnStore
  4. rpm、yum、编译安装轻松管理centos7程序包
  5. RHEL7.0系列 修改字符终端分辨率
  6. 8位无符号和8位有符号转化为更高字节类型的问题
  7. 面试题6:用两个栈实现队列
  8. SSH无需密码密钥登录
  9. iphone开发UITable内嵌不同风格Table
  10. 面试官问你想找什么工作_找工作时如何面试面试官