Spring Boot自动配置类

http://docs.spring.io/spring-boot/docs/current/api/overview-summary.html

http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#auto-configuration-classes

前提

1、一般来说,xxxAware接口,都提供了一个setXxx的方法,以便于其实现类将Xxx注入自身的xxx字段中,从而进行操作。

例如 ApplicationContextAware ,就提供了 void setApplicationContext(ApplicationContext applicationContext) throws BeansException,从而让其实现可以直接操作 applicationContext 。

2、Spring中的 BeanFactory,这是访问bean container 的root interface。其实现类的对象通常拥有一系列 bean 定义,并以不同的String 名字来区分。

但是,官方文档不建议直接使用这种方式获取bean,而是建议使用注入的方式获取bean(@Autowire)。--这个,前期不能使用初始化注入吧?

正文

Spring Boot提供的自动配置都是位于包 org.springframework.boot.autoconfigure 之下。

注意,

① 这里是Spring Boot提供的,而非第三方(如MyBatis-Spring-Boot-Starter)提供的。

② 不包含Spring Boot Actuator部分的。

Spring Boot的自动配置类可以通过autoconfig report查看,需要开启 --debug 或 -Debug。或者在 Actuator 项目的autoconfig 端点查看。

这里先从Web开始学习

由于Spring Boot的web Starter集成了Spring MVC,而非其他,所以实际上提供的Web自动配置为Spring MVC的自动配置。

Spring MVC的自动配置在包 org.springframework.boot.autoconfigure.web 之下,该包中的内容如下:

从上图中可以清楚的看到Spring Boot为Spring MVC提供了哪些自动配置:

  • DispatcherServletAutoConfiguration.class
  • EmbeddedServletContainerAutoConfiguration.class
  • ErrorMvcAutoConfiguration.class
  • GsonHttpMessageConvertersConfiguration.class
  • HttpEncodingAutoConfiguration.class
  • HttpMessageConvertersAutoConfiguration.class
  • JacksonHttpMessageConvertersConfiguration.class
  • MultipartAutoConfiguration.class
  • ServerPropertiesAutoConfiguration.class
  • WebClientAutoConfiguration.class
  • WebMvcAutoConfiguration.class

接下来,我们有针对性的来捋一遍。

一、先看一下 EmbeddedServletContainerAutoConfiguration,这是内置Servlet容器的自动配置 -- 默认就是那个 pivotal-tc-server (定制版tomcat,商业的)。

该类的声明如下:

 1 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) // 自动配置里面的最高优先级
 2 @Configuration
 3 @ConditionalOnWebApplication // 仅限于web应用
 4 @Import(BeanPostProcessorsRegistrar.class) // 导入内置容器的设置
 5 public class EmbeddedServletContainerAutoConfiguration {
 6     @Configuration
 7     @ConditionalOnClass({ Servlet.class, Tomcat.class })
 8     @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
 9     public static class EmbeddedTomcat {
10         // ...
11     }
12
13     @Configuration
14     @ConditionalOnClass({ Servlet.class, Server.class, Loader.class, WebAppContext.class })
15     @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
16     public static class EmbeddedJetty {
17         // ...
18     }
19
20     @Configuration
21     @ConditionalOnClass({ Servlet.class, Undertow.class, SslClientAuthMode.class })
22     @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
23     public static class EmbeddedUndertow {
24         // ...
25     }
26
27     public static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
28         // ...
29     }
30 }

@ConditionalOnWebApplication 是基于application context 是否 web application context 进行判断。

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) ,这里的 Ordered.HIGHEST_PRECEDENCE  其实是int类型的最小值,代表最高的优先级。

@Import(BeanPostProcessorsRegistrar.class,这里 BeanPostProcessorsRegistrar 中进行的操作是注册了一个bean,  EmbeddedServletContainerCustomizerBeanPostProcessor 。是通过 ImportBeanDefinitionRegistrar  进行早期注册。

这个配置类,内部共有4个静态内部类:3个容器类(tomcat、jetty、undertow)、1个bean注册类。

  1. 3个容器类是基于classpath中的class文件来判断使用哪个容器,默认使用内置容器。
  2. 1个bean注册类则是注册了一个 BeanPostProcessor bean,用于对容器进行定制。

下面重点看一下这个bean注册类的相关。

1、EmbeddedServletContainerCustomizerBeanPostProcessor

public class EmbeddedServletContainerCustomizerBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware {
    // ...
}

2、BeanPostProcessor接口,该接口内容如下:

1 public interface BeanPostProcessor {
2     Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
3     Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
4 }

根据方法的名字可以知道这是对在bean初始化之前、之后进行操作的方法。

该接口的Javadoc如下:

  1. BeanPostProcessor则是一个工厂钩子(factory hook),用于对新beans实例进行定制修改,例如检查它们的标记接口或者使用代理包装它们。
  2. ApplicationContexts能够自动探测BeanPostProcessor beans,并将他们应用到后续创建的任意beans中。
  3. 简单bean工厂允许代码化的注册post-processors,并将注册的post-processors应用到该工厂创建的所有bean中。
  4. 典型的做法是,通过标记接口装配beans时,post-processors会实现postProcessBeforeInitialization;而使用代理包装beans时则会实现postProcessAfterInitialization

EmbeddedServletContainerCustomizerBeanPostProcessor 中提供了 postProcessBeforeInitialization 的实现(对bean有更多的操作,而非直接返回bean),对内置容器进行了定制操作。(插一句,这里的定制操作是通过applicationContext 中 EmbeddedServletContainerCustomizer beans进行的,所以需要先获取applicationContext(ApplicationContextAware的功劳),再从applicationContext中获取EmbeddedServletContainerCustomizer beans)

3、回过头来再看一下BeanPostProcessorsRegistrar

1 public static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
2     // ...
3 }

这是个静态内部类,实现了两个接口。

4、接口ImportBeanDefinitionRegistrar

public interface ImportBeanDefinitionRegistrar {
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
}

该接口用于在系统处理@Configuration class时注册更多的bean。是bean定义级别的操作,而非@Bean method/instance级别的。

这个方法,应该是在Spring加载bean时被Spring调用。

org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader

未完待续。

时间: 2024-10-23 20:38:58

Spring Boot自动配置类的相关文章

Spring Boot自动配置原理(转)

第3章 Spring Boot自动配置原理 3.1 SpringBoot的核心组件模块 首先,我们来简单统计一下SpringBoot核心工程的源码java文件数量: 我们cd到spring-boot-autoconfigure工程根目录下.执行 $ tree | grep -c .java$ 模块 java文件数 spring-boot 551 spring-boot-actuator 423 spring-boot-autoconfigure 783 spring-boot-devtools

4、Spring Boot 自动配置原理

1.4 Spring Boot 自动配置原理 简介 spring boot自动配置功能可以根据不同情况来决定spring配置应该用哪个,不应该用哪个,举个例子: Spring的JdbcTemplate是不是在Classpath里面?如果是,并且DataSource也存在,就自动配置一个JdbcTemplate的Bean Thymeleaf是不是在Classpath里面?如果是,则自动配置Thymeleaf的模板解析器.视图解析器.模板引擎 那个这个是怎么实现的呢?原因就在于它利用了Spring的

Springboot 系列(三)Spring Boot 自动配置

注意:本 Spring Boot 系列文章基于 Spring Boot 版本 v2.1.1.RELEASE 进行学习分析,版本不同可能会有细微差别. 前言 关于配置文件可以配置的内容,在 Spring Boot 官方网站已经提供了完整了配置示例和解释. 可以这么说,Spring Boot 的一大精髓就是自动配置,为开发省去了大量的配置时间,可以更快的融入业务逻辑的开发,那么自动配置是怎么实现的呢? 1. @SpringBootApplication 跟着 Spring Boot 的启动类的注解

Spring Boot 自动配置之@Conditional的使用

Spring Boot自动配置的"魔法"是如何实现的? 转自-https://sylvanassun.github.io/2018/01/08/2018-01-08-spring_boot_auto_configure/ Spring Boot是Spring旗下众多的子项目之一,其理念是约定优于配置,它通过实现了自动配置(大多数用户平时习惯设置的配置作为默认配置)的功能来为用户快速构建出标准化的应用.Spring Boot的特点可以概述为如下几点: 内置了嵌入式的Tomcat.Jett

Spring Boot自动配置实例

spring boot之所以能够自动配置bean,是通过基于条件来配置Bean的能力实现的. 常用的条件注解如下 @ConditionalOnBean:当容器里存在指定的Bean的条件下 @ConditionalOnClass:当前类路径下存在指定的类的条件下 @ConditionalOnExpression:基于SpEL表达式作为判断条件 @ConditionalOnJava:基于JVM版本作为判断条件 @ConditionalOnJndi:在JNDI存在的条件下查找指定的位置 @Condit

Spring Boot自动配置源码解析(基于Spring Boot 2.0.2.RELEASE)

在Spring Boot官方介绍中,首一段话是这样的(如下图).我们可以大概了解到其所表达的含义:我们可以利用Spring Boot写很少的配置来创建一个非常方便的基于Spring整合第三方类库的单体企业级应用.相信使用过Spring Boot的人都知道,她在这方面从前到后的一系列整合.本篇文字将带你进入具体的实现细节. 首先我们写一段Spring Boot应用启动类的代码如下: 1 package com.springTest; 2 3 import org.springframework.b

spring boot 自动配置原理

1).spring boot启动的时候加载主配置类,开启了自动配置功能@EnableAutoConfiguration 2).通过@EnableAutoConfiguration中AutoConfigurationImportSelector给容器中导入了一系列的组件通过List<String> configurations = getCandidateConfigurations(annotationMetadata,attributes);获取候选的配置,下一步通过SpringFactor

spring boot自动配置实现

自从用了spring boot,都忘记spring mvc中的xml配置是个什么东西了,再也回不去.为啥spring boot这么好用呢, 约定大于配置的设计初衷, 让我们只知道维护好application.properties(或application.yml)文件就可以了,我们在配置文件里可以设置数据源参数,可以设置服务端口,可以设置redis的地址等等.我们经常会看一些包含starter名字的jar包,如spring-boot-starter-data-redis,引入这些jar包,我们就

Spring Boot自动配置总结

Spring Boot项目启动的时候加载主配置类,并开启了自动配置功能.(Spring Boot的自动配置功能是Spring Boot的一大重要且突出的特性) 那么我们需要了解下它: 如何加载主配置类? 通过@SpringBootApplication的注解来找到并加载主配置类. 如何开启自动配置功能? 点进@SpringBootApplication的源码后可以发现这样一段代码,说明@SpringBootApplication注解由多个注解组成. 其中,自动配置功能主要就是依靠@EnableA