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

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

前言

微信图片_20220413131610.jpg

关于配置文件可以配置的内容,在 Spring Boot 官方网站已经提供了完整了配置示例和解释。


可以这么说,Spring Boot 的一大精髓就是自动配置,为开发省去了大量的配置时间,可以更快的融入业务逻辑的开发,那么自动配置是怎么实现的呢?


1. `@SpringBootApplication`


跟着 Spring Boot 的启动类的注解 @SpringBootApplication 进行源码跟踪,寻找自动配置的原理。


@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 {


@EnableAutoConfiguration 开启自动配置。


@ComponentScan 开启注解扫描


SpringBootApplication 我们可以发现,这是一个简便的注解配置,它包含了自动配置,配置类,包扫描等一系列功能。


2. `@EnableAutoConfiguration`


继续跟踪,查看@EnableAutoConfiguration 源码,里面比较重要的是 @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 {};
}


继续跟踪 AutoConfigurationImportSelector.class .在这个类有一个重要的方法 getCandidateConfigurations.用于加载 Spring Boot 配置的自动配置类。


getAutoConfigurationEntry 会筛选出有效的自动配置类。


protected AutoConfigurationEntry getAutoConfigurationEntry(
            AutoConfigurationMetadata autoConfigurationMetadata,
            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 = filter(configurations, autoConfigurationMetadata);
        fireAutoConfigurationImportEvents(configurations, exclusions);
        return new AutoConfigurationEntry(configurations, exclusions);
    }   
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
            AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
                getSpringFactoriesLoaderFactoryClass(), 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;
    }


下图是 DEBUG 模式下筛选之后的结果,因为我只添加了 web 模块,所以只有 web 相关的自动配置。

微信图片_20220413131917.jpg

筛选过后的自动配置


3. xxxAutoConfiguration 与 xxxProperties


在上面的 debug 里,我们看到了成功加载的自动配置,目前只看到了配置类,却还没有发现自动配置值,随便选择一个 AutoConfiguration 查看源码。

这里选择了 ServletWebServerFactoryAutoConfiguration.


@Configuration
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
//判断当前项目有没有这个类
//CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器;
@ConditionalOnClass(ServletRequest.class)
//Spring底层@Conditional注解(Spring注解版),根据不同的条件,如果
//满足指定的条件,整个配置类里面的配置就会生效; 判断当前应用是否是web应用,如果是,当前配置类生效
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
        ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
        ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
        ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {


需要注意的是 @EnableConfigurationProperties(ServerProperties.class).他的意思是启动指定类的ConfigurationProperties功能;将配置文件中对应的值和 ServerProperties 绑定起来;并把ServerProperties 加入到 IOC 容器中。


再来看一下 ServerProperties .


@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {
    /**
     * Server HTTP port.
     */
    private Integer port;


显而易见了,这里使用 ConfigurationProperties 绑定属性映射文件中的 server 开头的属性。结合默认配置


# 路径spring-boot-autoconfigure-2.1.1.RELEASE.jar
# /META-INF/spring-configuration-metadata.json
    {
      "name": "server.port",
      "type": "java.lang.Integer",
      "description": "Server HTTP port.",
      "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties",
      "defaultValue": 8080
    }

达到了自动配置的目的。


4. 自动配置总结


  1. SpringBoot 启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration 。
  2. @EnableAutoConfiguration 给容器导入META-INF/spring.factories 里定义的自动配置类。
  3. 筛选有效的自动配置类。
  4. 每一个自动配置类结合对应的 xxxProperties.java 读取配置文件进行自动配置功能 。


5. 配置类


通过自动配置,我们发现已经帮我们省去了大量的配置文件的编写,那么在自定义配置的时候,我们是不是需要编写XML呢?Spring boot 尽管可以使用 SpringApplicationXML 文件进行配置,但是我们通常会使用 @Configuration 类进行代替,这也是官方推荐的方式。


5.1 XML配置


定义 helloService Bean.


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="helloService" class="net.codingme.boot.service.HelloService"></bean>
</beans>


引入配置。


@ImportResource(value = "classpath:spring-service.xml")
@SpringBootApplication
public class BootApplication {
    public static void main(String[] args) {
        SpringApplication.run(BootApplication.class, args);
    }
}


5.2 注解配置


此种方式和上面的XML配置是等效的,也是官方推荐的方式。


@Configuration 注解的类(要在扫描的包路径中)会被扫描到。


/**
 * <p>
 * 配置类,相当于传统Spring 开发中的 xml-> bean的配置
 *
 * @Author niujinpeng
 * @Date 2018/12/7 0:04
 */
@Configuration
public class ServiceConfig {
    /**
     * 默认添加到容器中的 ID 为方法名(helloService)
     *
     * @return
     */
    @Bean
    public HelloService helloService() {
        return new HelloService();
    }
}


6. 附录

@Conditional扩展注解 作用(判断是否满足当前指定条件)
@ConditionalOnJava 系统的java版本是否符合要求
@ConditionalOnBean 容器中存在指定Bean;
@ConditionalOnMissingBean 容器中不存在指定Bean;
@ConditionalOnExpression 满足SpEL表达式指定
@ConditionalOnClass 系统中有指定的类
@ConditionalOnMissingClass 系统中没有指定的类
@ConditionalOnSingleCandidate 容器中只有一个指定的Bean,或者这个Bean是首选Bean
@ConditionalOnProperty 系统中指定的属性是否有指定的值
@ConditionalOnResource 类路径下是否存在指定资源文件
@ConditionalOnWebApplication 当前是web环境
@ConditionalOnNotWebApplication 当前不是web环境
@ConditionalOnJndi JNDI存在指定项
相关文章
|
2月前
|
Java Spring
【Spring】方法注解@Bean,配置类扫描路径
@Bean方法注解,如何在同一个类下面定义多个Bean对象,配置扫描路径
175 73
|
11天前
|
XML Java 应用服务中间件
Spring Boot 两种部署到服务器的方式
本文介绍了Spring Boot项目的两种部署方式:jar包和war包。Jar包方式使用内置Tomcat,只需配置JDK 1.8及以上环境,通过`nohup java -jar`命令后台运行,并开放服务器端口即可访问。War包则需将项目打包后放入外部Tomcat的webapps目录,修改启动类继承`SpringBootServletInitializer`并调整pom.xml中的打包类型为war,最后启动Tomcat访问应用。两者各有优劣,jar包更简单便捷,而war包适合传统部署场景。需要注意的是,war包部署时,内置Tomcat的端口配置不会生效。
106 17
Spring Boot 两种部署到服务器的方式
|
6天前
|
监控 Java 应用服务中间件
SpringBoot是如何简化Spring开发的,以及SpringBoot的特性以及源码分析
Spring Boot 通过简化配置、自动配置和嵌入式服务器等特性,大大简化了 Spring 应用的开发过程。它通过提供一系列 `starter` 依赖和开箱即用的默认配置,使开发者能够更专注于业务逻辑而非繁琐的配置。Spring Boot 的自动配置机制和强大的 Actuator 功能进一步提升了开发效率和应用的可维护性。通过对其源码的分析,可以更深入地理解其内部工作机制,从而更好地利用其特性进行开发。
20 6
|
12天前
|
监控 Java 数据库连接
Spring c3p0配置详解
在Spring项目中配置C3P0数据源,可以显著提高数据库连接的效率和应用程序的性能。通过合理的配置和优化,可以充分发挥C3P0的优势,满足不同应用场景的需求。希望本文的详解和示例代码能为开发者提供清晰的指导,帮助实现高效的数据库连接管理。
32 10
|
19天前
|
缓存 安全 Java
Spring Boot 3 集成 Spring Security + JWT
本文详细介绍了如何使用Spring Boot 3和Spring Security集成JWT,实现前后端分离的安全认证概述了从入门到引入数据库,再到使用JWT的完整流程。列举了项目中用到的关键依赖,如MyBatis-Plus、Hutool等。简要提及了系统配置表、部门表、字典表等表结构。使用Hutool-jwt工具类进行JWT校验。配置忽略路径、禁用CSRF、添加JWT校验过滤器等。实现登录接口,返回token等信息。
202 12
|
25天前
|
存储 安全 Java
Spring Boot 3 集成Spring AOP实现系统日志记录
本文介绍了如何在Spring Boot 3中集成Spring AOP实现系统日志记录功能。通过定义`SysLog`注解和配置相应的AOP切面,可以在方法执行前后自动记录日志信息,包括操作的开始时间、结束时间、请求参数、返回结果、异常信息等,并将这些信息保存到数据库中。此外,还使用了`ThreadLocal`变量来存储每个线程独立的日志数据,确保线程安全。文中还展示了项目实战中的部分代码片段,以及基于Spring Boot 3 + Vue 3构建的快速开发框架的简介与内置功能列表。此框架结合了当前主流技术栈,提供了用户管理、权限控制、接口文档自动生成等多项实用特性。
72 8
|
2月前
|
Java Spring
【Spring配置相关】启动类为Current File,如何更改
问题场景:当我们切换类的界面的时候,重新启动的按钮是灰色的,不能使用,并且只有一个Current File 项目,下面介绍两种方法来解决这个问题。
|
2月前
|
Java Spring
【Spring配置】idea编码格式导致注解汉字无法保存
问题一:对于同一个项目,我们在使用idea的过程中,使用汉字注解完后,再打开该项目,汉字变成乱码问题二:本来a项目中,汉字注解调试好了,没有乱码了,但是创建出来的新的项目,写的注解又成乱码了。
|
2月前
|
Java Spring
【Spring配置】创建yml文件和properties或yml文件没有绿叶
本文主要针对,一个项目中怎么创建yml和properties两种不同文件,进行配置,和启动类没有绿叶标识进行解决。
|
安全 Java 应用服务中间件
SpringBoot核心【基本配置】
基本配置 1.入口类和相关注解 2.定制Banner 2.1 修改banner图标 2.2 关闭banner 3.SpringBoot的配置文件 3.1 tomcat端口号修改 3.2 常规属性配置 3.3 类型安全的配置
SpringBoot核心【基本配置】