SpringBoot自动配置的原理及实现
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/> <!– lookup parent from repository –></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自动配置是怎么运行的
- 当SpringBoot项目启动时,会先去扫描所有jar包下的META-INF/spring.factories配置文件
2.通过读取spring.factories配置文件得到所有自动配置类的全限定类名,并将这些自动配置类全部注入到IOC容器
3.那么多类是全部都注入进去?当然不是,在这些配置类中都有条件注解,这些条件注解会去判断是否要导入
4.经过以上步骤,就实现了自动配置的过程,当然详细的实现细节肯定不会这么简单
SpringBoot自动配置的原理及实现相关推荐
- SpringBoot自动配置Redis原理
SpringBoot自动配置Redis原理 目录 SpringBoot自动配置Redis原理 一.SpringBoot自动配置Redis原理 一.自动配置redis RedisAutoConfigur ...
- springboot自动配置的原理_SpringBoot实战:详解SpringBoot自动配置原理
SpringBoot 自动配置主要通过 @EnableAutoConfiguration, @Conditional, @EnableConfigurationProperties 或者 @Confi ...
- springboot自动配置的原理_SpringBoot自动配置原理
SpringBoot的启动入口就是一个非常简单的run方法,这个run方法会加载一个应用所需要的所有资源和配置,最后启动应用. 通过查看run方法的源码,我们发现,run方法首先启动了一个监听器,然后 ...
- SpringBoot自动配置MVC原理
SpringBoot自动配置了MVC究竟都配置了那些东西,该如何自定义呢? 摸了!直接看官方文档(其实我也看不大懂英语) https://docs.spring.io/spring-boot/docs ...
- 聊一聊 SpringBoot 自动配置的原理
解析思路 我们建立好一个SpringBoot的工程后,我们将从启动类,SpringBootApplication开始进行探究. 开始解析 首先我们建立一个 Springboot的工程.找到启动类,我们 ...
- SpringBoot自动配置实现原理及源码解析(2.3.x)
约定优于配置,这是SpringBoot中的一个很重要特性,此特性让我们可以在几秒中之内完成一个项目的搭建,无需任何配置,本文就通过深入源码的方式来探索下自动配置的实现过程 为什么要自动配置 手动配置很 ...
- 笑死,面试官又问我SpringBoot自动配置原理
面试官:好久没见,甚是想念.今天来聊聊SpringBoot的自动配置吧? 候选者:嗯,SpringBoot的自动配置我觉得是SpringBoot很重要的"特性"了.众所周知,Spr ...
- 这样讲 SpringBoot 自动配置原理,你应该能明白了吧
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:你在我家门口 juejin.im/post/5ce5effb ...
- 今天,我们来详细的聊一聊SpringBoot自动配置原理,学了这么久,你学废了吗?
SpringBoot是我们经常使用的框架,那么你能不能针对SpringBoot实现自动配置做一个详细的介绍.如果可以的话,能不能画一下实现自动配置的流程图.牵扯到哪些关键类,以及哪些关键点. 下面我们 ...
最新文章
- 恶意软件盯上了加密货币,两家以色列公司受到攻击
- Nature重磅综述|关于RNA-seq,你想知道的都在这(续)
- 一像素约束(选中所需约束,切换到类处,选择此类,运行时就是0.5的约束)
- Spring的bean管理(注解注入属性)
- 创建一个简单的MFC程序
- TCP/IP常见攻击手段
- python turtle菜鸟教程_【读书】Django教程(菜鸟教程)
- Comparing Mongo DB and Couch DB
- 输出纹波和纹波电流测试规范分享
- 【知识图谱问答】DBpedia介绍
- 洪水填充算法_洪水填充算法分析
- ssm+Vue计算机毕业设计学科竞赛赛场安排系统(程序+LW文档)
- web前端入门到实战:CSS颜色、背景和剪切
- html网页设计大赛作品介绍,HTML网页设计大赛--赛出风采
- 家庭光纤宽带有必要升级千兆双频路由器吗?
- webdav服务器文件大小限制,WebDAV服务器
- 【牛客网】树根与星际密码
- h5网页服务器选择,h5制作选择虚拟主机还是服务器
- linux修改u盘卷标,如何在Linux下格式化U盘以及修改卷标
- 使用Deal.II过程