Spring Boot学习笔记(十二):Spring Boot 自动配置原理分析

前言

        不论在工作中,亦或是求职面试,Spring Boot 已经成为我们必知必会的技能项。除了某些老旧的政府项目或金融项目持有观望态度外,如今的各行各业都在飞速的拥抱这个已经不是很新的Spring启动框架。

        当然,作为 Spring Boot 的精髓,自动配置原理的工作过程往往只有在"面试"的时候才能用得上,但是如果在工作中你能够深入的理解Spring Boot的自动配置原理,将无往不利。

        Spring Boot 的出现,得益于"约定优于配置"的理念,没有繁琐的配置、难以集成的内容(大多数流行第三方技术都被集成),这是基于 Spring 4.x 提供的按条件配置 Bean 的能力。

1.Spring Boot的配置文件

        初识 Spring Boot 时我们就知道,Spring Boot 有一个全局配置文件:application.properties 或 application.yml

        我们的各种属性都可以在这个文件中进行配置,最常配置的比如:server.portlogging.level.* 等等,然而我们实际用到的往往只是很少的一部分,那么这些属性是否有据可依呢?答案当然是肯定的,这些属性都可以在官方文档中查找到的,请点击我,我是官方文档
在这里插入图片描述
        除了官方文档为我们提供了大量的属性解释,我们也可以使用 IDE 的相关提示功能,比如IDEA的自动提示,如下所示:
在这里插入图片描述
以上,就是 Spring Boot 的配置文件的大致使用方法,其实都是些题外话。

       那么问题来了:这些配置是如何在 Spring Boot 项目中生效的呢?那么接下来,就需要聚焦本篇博客的主题:自动配置工作原理分析。

2.Spring Boot 自动配置原理分析

        我们在之前已经对Spring Boot 启动中使用到的 @SpringBootApplication 注解有过一个简短的了解,你可以参考这篇内容:@SpringBootApplication注解分析。看完这篇文章,我们就知道了 Spring Boot 关于自动配置的源码都是在 spring-boot-autoconfigure-x.x.x.x.jar 中:

       当然,自动配置原理的相关描述,官方文档貌似是没有提及。不过我们不难猜出,Spring Boot 的启动类上有一个@SpringBootApplication注解,这个注解是Spring Boot 项目必不可少的注解。自动配置原理就是和这个注解有着千丝万缕的联系!
在这里插入图片描述
       @SpringBootApplication是一个复合注解,该注解被@EnableAutoConfiguration 注解,该注解的意识就是:开启自动配置,其定义如下:
在这里插入图片描述
       这个注解也是一个符合注解,我们关键来了解@Import这个注解,它的意思就是通过AutoConfigurationImportSelector这个类来进行相关的操作。我们发现该类中有重写了一个 selectImports()方法,它是通过 SpringFactoriesLoader.loadFactoryNames() 的方式,扫描所有位于META-INF/spring.factories文件下的jar包。在 META-INF 路径下,我们一共看到了两个spring.factories 文件。如下图所示:
在这里插入图片描述
       关于Spring Boot 自动配置的相关项,是在 spring-boot-autoconfigure-x.x.x.x.jar 这个jar包下,如图所示。

       这个 spring.factories 文件中的内容,也是以我们常见的 key=value 的形式,其中一个key是 EnableAutoConfiguration 类的全类名,而它的value是一个xxxxAutoConfiguration 的类名的列表,这些类名以逗号分隔,如下图所示:
在这里插入图片描述
       这个 @EnableAutoConfiguration 注解通过@SpringBootApplication 被间接的标记在了Spring 的启动类上。在执行 SpringApplication.run(…) 的内部就会执行selectImports()方法,找到所有 JavaConfig 自动配置类的全限定名对应的 class,然后将所有自动配置类加载到Spring容器中。

3.如何使自动配置自动生效

       接下来,我们就对 xxxAutoConfiguration 这些自动配置类进行分析,看看他们是如何自动生效的,我们在每一个 xxxAutoConfiguration 类上都会看到有很多注解的存在。在此处,我们以:HttpEncodingAutoConfiguration 类进行分析。

@Configuration
@EnableConfigurationProperties(HttpEncodingProperties.class)
@ConditionalOnWebApplication
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {

	private final HttpEncodingProperties properties;

	public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
		this.properties = properties;
	}

	@Bean //给容器中添加一个组件,这个组件的某些值需要从properties中获取
	@ConditionalOnMissingBean(CharacterEncodingFilter.class) //判断容器没有这个 CharacterEncodingFilter 组件
	public CharacterEncodingFilter characterEncodingFilter() {
		CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
		filter.setEncoding(this.properties.getCharset().name());
		filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
		filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
		return filter;
	}
}

首先对这几个注解进行一番介绍:

@Configuration   //表示当前类是一个配置类

@EnableConfigurationProperties(HttpEncodingProperties.class) //启动指定类的ConfigurationProperties功能;将配置文件中对应的值和HttpEncodingProperties绑定起来;并把HttpEncodingProperties加入到ioc容器中(HttpEncodingProperties类有被@ConfigurationProperties 注解)

@ConditionalOnWebApplication //判断当前应用是否是web应用,如果是,当前配置类生效

@ConditionalOnClass(CharacterEncodingFilter.class) //判断当前项目有没有这个(CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器)

@ConditionalOnProperty(prefix = “spring.http.encoding”, value = “enabled”, matchIfMissing = true) //判断配置文件中是否存在某个配置 spring.http.encoding.enabled;如果不存在,判断也是成立的。即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的;

        通过如上多个注解的层层判断,便能够决定当前配置文件是否生效。只要不满足其中一个条件,都是不会被自动配置到 Spring 容器中的。

4.如何查看哪些自动配置已经加载到 Spring 容器

       既然 Spring Boot 已经为我们整合了N多场景下的自动配置类。但是在容器启动之后,我们怎么来查看Spring 容器中有哪些被自动配置了呢?这是后我们就用到了 Spring Boot 为我们提供的 debug功能

       我们可以在 application.yml/properties 主配置文件中,通过 debug: true 的方式来开启 Debug 模式,来让控制台打印自动配置报告。在项目启动时,它会为我们提供一个 AUTO-CONFIGURATION REPORT(自动配置报告),在这份报告中,我们便能够一目了然的看到,哪些组件已经加载到 Spring 容器中。

自动报告内容很多,此处附部分内容:

=========================
AUTO-CONFIGURATION REPORT
=========================


Positive matches:(已启用的配置)
-----------------

   DispatcherServletAutoConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
      - @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)

   DispatcherServletAutoConfiguration.DispatcherServletConfiguration matched:
      - @ConditionalOnClass found required class 'javax.servlet.ServletRegistration'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
      - Default DispatcherServlet did not find dispatcher servlet beans (DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition)

   DispatcherServletAutoConfiguration.DispatcherServletRegistrationConfiguration matched:
      - @ConditionalOnClass found required class 'javax.servlet.ServletRegistration'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
      - DispatcherServlet Registration did not find servlet registration bean (DispatcherServletAutoConfiguration.DispatcherServletRegistrationCondition)

Negative matches:(未启用的配置)
-----------------

   ActiveMQAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition)

   AopAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required classes 'org.aspectj.lang.annotation.Aspect', 'org.aspectj.lang.reflect.Advice' (OnClassCondition)

   ArtemisAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory' (OnClassCondition)


本文部分文字内容,摘自:https://blog.csdn.net/u014745069/article/details/83820511


Spring Boot 自动配置原理分析,介绍到此为止

如果本文对你有所帮助,那就给我点个赞呗 O(∩_∩)O

End

发布了301 篇原创文章 · 获赞 66 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/lzb348110175/article/details/105158139