目录

一、@SpringBootApplication

二、@EnableAutoConfiguration

1.AutoConfigurationPackages.Registrar.class 批量注册组件

2.AutoConfigurationImportSelector.class

三、按需开启自动配置

1.得益于按条件装配@Conditional

2.例如AOP:

四、总结

五、springboot快速配置


一、@SpringBootApplication

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration // 就是@Configuration。代表当前是一个配置类
@EnableAutoConfiguration // 开启自动配置
// 指定扫描哪些,Spring注解
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

二、@EnableAutoConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage //
@Import(AutoConfigurationImportSelector.class) // 给容器中导入一个组件
public @interface EnableAutoConfiguration {

1.AutoConfigurationPackages.Registrar.class 批量注册组件

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class) //给容器中导入一个组件
public @interface AutoConfigurationPackage {
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {@Overridepublic void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {// 注册注解包名下面所有的组件register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));}@Overridepublic Set<Object> determineImports(AnnotationMetadata metadata) {return Collections.singleton(new PackageImports(metadata));}}

2.AutoConfigurationImportSelector.class

(1)、利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件

(2)、调用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类

(3)、利用工厂加载 Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader);得到所有的组件

(4)、从META-INF/spring.factories位置来加载一个文件。

默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件

文件里面写死了spring-boot一启动就要给容器中加载的所有配置类

spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories

虽然我们127个场景的所有自动配置启动的时候默认全部加载。xxxxAutoConfiguration

按照条件装配规则(@Conditional),最终会按需配置。

// org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getAutoConfigurationEntry
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return EMPTY_ENTRY;}AnnotationAttributes attributes = getAttributes(annotationMetadata);List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);configurations = removeDuplicates(configurations);Set<String> exclusions = getExclusions(annotationMetadata, attributes);checkExcludedClasses(configurations, exclusions);configurations.removeAll(exclusions);configurations = getConfigurationClassFilter().filter(configurations);fireAutoConfigurationImportEvents(configurations, exclusions);return new AutoConfigurationEntry(configurations, exclusions);
}

三、按需开启自动配置

1.得益于按条件装配@Conditional

可修饰在类、方法上。
@ConditionalOnBean // 当容器中存在指定的组件时才。。。
@ConditionalOnMissingBean // 当容器中不存在指定的组件时才。。。
@ConditionalOnClass // 当容器中有某一个类时才。。。
@ConditionalOnMissingClass // 当容器中没有某一个类时才。。。
@ConditionalOnResource // 当项目类路径存在某个资源时才。。。
@ConditionalOnJava // 当项目环境是指定的java版本号时才。。。
@ConditionalOnWebApplication // 当应用是一个web应用时才。。。
@ConditionalOnSingleCandidate // 当容器中只有一个实例或者有用@Primary修饰的默认bean。
@ConditionalOnProperty // 当配置文件中配置了某个属性时才。。。@ConditionalOnBean(name = "tom")
@ConditionalOnMissingBean(name = "tom")

2.例如AOP:

假如说配置文件没有spring.aop.auto=true,matchIfMissing默认就是true,默认就是开启AOP。

我们可以看到里面有大量使用@Conditional判断。

package org.springframework.boot.autoconfigure.aop;import org.aspectj.weaver.Advice;
import org.springframework.aop.config.AopConfigUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;/**
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
* Auto-configuration} for Spring's AOP support. Equivalent to enabling
* {@link EnableAspectJAutoProxy @EnableAspectJAutoProxy} in your configuration.
* <p>
* The configuration will not be activated if {@literal spring.aop.auto=false}. The
* {@literal proxyTargetClass} attribute will be {@literal true}, by default, but can be
* overridden by specifying {@literal spring.aop.proxy-target-class=false}.
*
* @author Dave Syer
* @author Josh Long
* @since 1.0.0
* @see EnableAspectJAutoProxy
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {@Configuration(proxyBeanMethods = false)@ConditionalOnClass(Advice.class)static class AspectJAutoProxyingConfiguration {@Configuration(proxyBeanMethods = false)@EnableAspectJAutoProxy(proxyTargetClass = false)@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",matchIfMissing = false)static class JdkDynamicAutoProxyConfiguration {}@Configuration(proxyBeanMethods = false)@EnableAspectJAutoProxy(proxyTargetClass = true)@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",matchIfMissing = true)static class CglibAutoProxyConfiguration {}}@Configuration(proxyBeanMethods = false)@ConditionalOnMissingClass("org.aspectj.weaver.Advice")@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",matchIfMissing = true)static class ClassProxyingConfiguration {ClassProxyingConfiguration(BeanFactory beanFactory) {if (beanFactory instanceof BeanDefinitionRegistry) {BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);}}}
}
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass(DispatcherServlet.class)
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
public class DispatcherServletAutoConfiguration {/** The bean name for a DispatcherServlet that will be mapped to the root URL "/"*/public static final String DEFAULT_DISPATCHER_SERVLET_BEAN_NAME = "dispatcherServlet";/** The bean name for a ServletRegistrationBean for the DispatcherServlet "/"*/public static final String DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME = "dispatcherServletRegistration";@Configuration(proxyBeanMethods = false)@Conditional(DefaultDispatcherServletCondition.class)@ConditionalOnClass(ServletRegistration.class)@EnableConfigurationProperties(WebMvcProperties.class)protected static class DispatcherServletConfiguration {@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) {DispatcherServlet dispatcherServlet = new DispatcherServlet();dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound());dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents());dispatcherServlet.setEnableLoggingRequestDetails(webMvcProperties.isLogRequestDetails());return dispatcherServlet;}//给容器中加入了文件上传解析器@Bean@ConditionalOnBean(MultipartResolver.class)//容器中有这个类型组件@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)//容器中没有这个名字 multipartResolver 的组件public MultipartResolver multipartResolver(MultipartResolver resolver) {//给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找。//SpringMVC multipartResolver。防止有些用户配置的文件上传解析器不符合规范// Detect if the user has created a MultipartResolver but named it incorrectlyreturn resolver;}}@Configuration(proxyBeanMethods = false)@Conditional(DispatcherServletRegistrationCondition.class)@ConditionalOnClass(ServletRegistration.class)@EnableConfigurationProperties(WebMvcProperties.class)@Import(DispatcherServletConfiguration.class)protected static class DispatcherServletRegistrationConfiguration {@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)@ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet,WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet,webMvcProperties.getServlet().getPath());registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());multipartConfig.ifAvailable(registration::setMultipartConfig);return registration;}}
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(ServerProperties.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {private final Encoding properties;public HttpEncodingAutoConfiguration(ServerProperties properties) {this.properties = properties.getServlet().getEncoding();}@Bean@ConditionalOnMissingBeanpublic CharacterEncodingFilter characterEncodingFilter() {CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();filter.setEncoding(this.properties.getCharset().name());filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST));filter.setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE));return filter;}@Beanpublic LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {return new LocaleCharsetMappingsCustomizer(this.properties);}static class LocaleCharsetMappingsCustomizerimplements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>, Ordered {private final Encoding properties;LocaleCharsetMappingsCustomizer(Encoding properties) {this.properties = properties;}@Overridepublic void customize(ConfigurableServletWebServerFactory factory) {if (this.properties.getMapping() != null) {factory.setLocaleCharsetMappings(this.properties.getMapping());}}@Overridepublic int getOrder() {return 0;}}}

四、总结

* SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration

* 每个自动配置类按照条件进行生效(@Conditionalxxxx),默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定

* 生效的配置类就会给容器中装配很多组件

* 只要容器中有这些组件,相当于这些功能就有了

* SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先(@ConditionalOnMissingBean)

*定制化配置:① 用户直接自己@Bean替换底层的组件② 用户去看这个组件是获取的配置文件什么值就去修改。

xxxxxAutoConfiguration ---> 组件 ---> xxxxProperties里面拿值 ----> application.properties

五、springboot快速配置

1.引入场景依赖

https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter

2.查看自动配置了哪些(选做)

自己分析,引入场景对应的自动配置一般都生效了

配置文件中debug=true开启自动配置报告。Negative(不生效)\Positive(生效)

3.修改配置项

(1)参照文档修改配置项

https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties

(2)自己分析。xxxxProperties绑定了配置文件的哪些。

4.自定义加入或者替换组件

@Bean、@Component。。。

5.自定义器 XXXXXCustomizer

springboot-自动配置原理相关推荐

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

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

  2. SpringBoot | 自动配置原理

    微信公众号:一个优秀的废人.如有问题,请后台留言,反正我也不会听. 前言 这个月过去两天了,这篇文章才跟大家见面,最近比较累,大家见谅下.下班后闲着无聊看了下 SpringBoot 中的自动配置,把我 ...

  3. 【详解】面试必问:SpringBoot自动配置原理

    前言 SpringBoot框架是开发中的一大利器,其简化了spring的xml的配置,遵循了"约定大于配置"的原则,使用注解对常用的配置做默认配置,减少使用xml配置模式.Spri ...

  4. SpringBoot 自动配置原理(超级无敌详细)-2

    SpringBoot 自动配置原理(超级无敌详细)-1 2.自动配置的实现 刚刚我们整体的过了一下主配置文件是如何实现的,但我们还没深入的研究如何实现自动装配功能.我们回到这个文件下,找一个具体的自动 ...

  5. SpringBoot实战之SpringBoot自动配置原理

    www.cnblogs.com/leihuazhe/p- SpringBoot 自动配置主要通过 @EnableAutoConfiguration, @Conditional, @EnableConf ...

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

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

  7. SpringBoot 自动配置原理

    创建项目 通过Spring Initialize创建SpringBoot项目 而接下来要说的是关于配置文件的事情.关乎配置文件可以参考官方文档. 对于配置文件来说到底在配置文件里面可以进行配置那些内容 ...

  8. springboot自动配置原理_今日份学习之Spring Boot自动配置实现原理

    通过前面章节的学习,我们掌握了使用Spring Boot框架进行实际应用开发的方法.在使用Spring Boot 的过程中,我们时常会为一些看似简单,但实际上蕴藏了强大功能的实现而惊呼,下面就让我们来 ...

  9. springboot自动配置原理

    概述 Springboot的基本认识 对于Spring框架,我们接触得比较多的是Spring mvc,Spring IOC.AOP.DI.而这框架如果在使用过程中,随着项目越来越大,引入的技术越来越多 ...

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

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

最新文章

  1. TensorFlow教程:快速入门深度学习五步法(附Keras实例)
  2. Servlet + JSP(EL表达式)
  3. 圈子 | 大数据分析汽车O2O的机会
  4. Python即时网络爬虫项目: 内容提取器的定义(Python2.7版本)
  5. 生成式模型:LDA与LSI-SVD分解
  6. spring5.0.2中文官网文档pdf
  7. 如何使用Restic Backup Client将数据备份到对象存储服务
  8. DDL、DML、DQL、DCL 理解
  9. add jar and proxy repo
  10. mysql ssl编译_MySQL8开启ssl加密
  11. CANape操作指南
  12. ubuntu16.04安装monaco字体
  13. 如何下载行政区划地图
  14. android 行政区域,最新Android使用Jsoup获取省市县行政区划代码行政编码(附源码与Json数据)...
  15. DX C++实现超炫酷粒子特效之烟花特效
  16. java统计学生上课出勤_javaweb课堂考勤管理系统
  17. 操作系统实验一:进程管理(含成功运行C语言源代码)
  18. 计算机科学箴言集 -- 编程珠玑续
  19. Viusal 各个版本离线镜像
  20. CSDN 图片加载不出来

热门文章

  1. JS 中迭代数组的三种方法
  2. 阿里云服务器中毒‘Kirito666’经历
  3. matlab与钻井平台,基于MATLAB环境下采用C8051F060实现钻井井眼姿态监测系统的设计...
  4. php trimmsg,c语言实现php的trim标签
  5. python程序格式框架的描述_python 程序语言设计(嵩天)-学习笔记(第二章python 程序实例解析)...
  6. QT最方便的LOG库使用Easylogging++,只需要一个头文件
  7. linux指令popd,Linux切换目录pushd、popd、dirs命令
  8. eureka java_spring cloud 入门系列二:使用Eureka 进行服务治理
  9. 单单表单独占一行_数据透视表→Alt+D+P?
  10. python3中的dict循环性能对比