SpringBoot如何做自动配置

news2024/9/21 22:45:43

目录

一、什么是springboot的自动配置?

二、@Enable注解

三、springboot自动配置流程

@ComponentScan

@SpringBootConfiguration

@EnableAutoConfiguration注解

condition的几个注解:

四、自定义启动类

需求:

参考:

实现步骤:


一、什么是springboot的自动配置?

        Spring Boot通过@EnableAutoConfiguration注解开启自动配置,对autoconfigured的jar包下的META-INF下的spring包中下的spring.factories文件进行扫描,这个文件中包含了可以进行自动配置的类,当满足@Condition注解指定的条件时,便在依赖的支持下进行实例化,注册到Spring容器中。

        用注解来对一些常规的配置做默认配置,简化了各种xml配置内容,使项目能够快速运行。自动装配最明显的特征就是不用xml文件去做配置,而是用到properties文件或者yml文件,在pom.xml中简单地写一些坐标就能实现各类负载地配置。自动将Bean装配到IOC容器中

二、@Enable注解

SpringBoot 中提供了很多 Enable 开头的注解,这些注解都是用于动态启用某些功能的。而其底层原理是使用 @Import注解 导入一些配置类,实现 Bean 的动态加载
思考 SpringBoot 工程是否可以直接获取 jar 包中定义的 Bean
@Import 注解
@Enable 底层依赖于 @Import 注解导入一些类,使用 @Import 导入的类会被 Spring 加载到 IOC 容器中。 而@Import 提供 4 中用法:
① 导入 Bean
② 导入配置类
③ 导入 ImportSelector 实现类。一般用于加载配置文件中的类
④ 导入 ImportBeanDefinitionRegistrar 实现类。

//MyImportSelector

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //目前字符串数组内容是写死的,未来可以设置在配置文件中动态加载
        return new String[]{"com.apesource.springbootenableother04.domain.User","com.apesource.springbootenableother04.domain.Student"};
    }
}




//MyImportBeanDefinitionRegistrar


public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //AnnotationMetadata注解
        //BeanDefinitionRegistry向spring容器中注入

        //获取user的definition对象
        AbstractBeanDefinition beanDefinition= BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();

        //通过beanDefinition属性信息,向Spring容器中注册id为user的对象
        registry.registerBeanDefinition("user",beanDefinition);
    }
}




//UserConfig
@Configuration
public class UserConfig {
    @Bean
    public User user(){
        return new User();
    }
}



//EnableUser 
@Target(value = ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(UserConfig.class)
public @interface EnableUser {
}

三、springboot自动配置流程

springboot的启动类main方法上有一个springboot的核心注解@SpringbootApplication

按ctrl点进去

@ComponentScan
这个注解在 Spring 中很重要 , 它对应 XML 配置中的元素。
作用:自动扫描并加载符合条件的组件或者 bean , 将这个 bean 定义加载到 IOC 容器中
@SpringBootConfiguration
作用: SpringBoot 的配置类 ,标注在某个类上 , 表示这是一个 SpringBoot 的配置类;
@EnableAutoConfiguration注解

主要作用是开启自动配置

而@EnableAutoConfiguration也是一个复合注解,它包含了@AutoConfigurationPackage@Import({AutoConfigurationImportSelector.class})。

@AutoConfigurationPackage注解,自动配置包。点进去可以看到就是⼀个 @Import 注解:@Import(Registrar.class) ,导⼊了⼀个Registrar 的组件,这个注解的作用就是将主配置类(@SpringBootConfiguration标注的类)所在的包及其下面所有子包里面所有的组件扫描到IOC容器中

而@Import(AutoConfigurationImportSelector.class)注解通过@Import导入了AutoConfigurationImportSelector类,而这个类的selectImports方法会通过SpringFactoriesLoader(这个类实现了检索META-INF/spring.factories文件,并获取指定接口的配置的功能)得到大量的配置类,当 SpringBoot 应用启动时,会自动加载这些配置类,初始化Bean 。而每个配置类则根据条件化配置类做出决策,以实现自动配置的功能。

  1. SpringFactoriesLoader 机制:Spring Boot 在 META-INF/spring.factories 文件中定义了自动配置类的列表。在启动时,通过 SpringFactoriesLoader 加载这些配置类,并根据条件进行处理。

我们写配置类只需要加入一个@Configuration注解,Springboot就可以轻松地自己找到想要地目标文件。

并不是所有的Bean都会被初始化,需要在配置类中使用Condition来加载满足条件的Bean

condition的几个注解:

ConditionalOnProperty:用来判断配置文件中是否有对应属性和值才初始化Bean
ConditionalOnClass:用来判断环境中是否有对应字节码文件才初始化Bean
ConditionalOnMissingBean:用来判断环境中没有对应Bean才初始化Bean
ConditionalOnBean:用来判断环境中有对应Bean才初始化Bean

综上所述大概就是:
Spring Boot 的 自动配置流程大致如下:
1. 启动应用:当运行 Spring Boot 应用时,首先会 加载主启动类
2. 依赖解析:Spring Boot 会检查项目中引入的依赖。
3. 加载 `spring.factories` 文件:查找并加载 `META-INF/spring.factories` 文件,该文件中定          义了各种自动配置类。
4. 条件判断:对于每个自动配置类,根据条件注解(如 `@ConditionalOnClass`、           `@ConditionalOnProperty` 等)进行判断。
         - 如果条件满足,相关的配置类会被加载。
         - 如果条件不满足,则跳过该配置。
5. 配置生效:满足条件的配置类中的配置逻辑被执行,完成相关组件的自动配置。
6. 应用上下文准备:将自动配置好的组件注册到 Spring 应用上下文     (ApplicationContext) 中,使其可供应用使用。
7. 启动完成:完成自动配置和组件注册后,应用启动完成,开始处理业务逻辑。
        例如,如果项目中添加了数据库相关的依赖,并且配置文件中提供了正确的数据库连接信息,那么相应的数据库自动配置类会在条件满足的情况下被加载和执行,完成数据库连接池等的配置。

四、自定义启动类

需求:
自定义 redis-starter ,要求当导入 redis 坐标时, SpringBoot 自动创建 Jedis Bean
参考:
可以参考 mybatis 启动类的应用
实现步骤:
1、创建redis-spring-boot-autoconfigure模块
2、创建redis-spring-boot-starter模块,依赖redis-spring-boot-autoconfigure的模块
<!--引入自定义的redis-spring-boot-autoconfigure-->
        <dependency>
            <groupId>com.apesource</groupId>
            <artifactId>redis-spring-boot-autoconfigure</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

3、在redis-spring-boot-autoconfigure模块中初始化JedisBean,并定义META
INF/spring.factories文件
redis-spring-boot-autoconfigure的pom.xml文件中:
<!--引入jedis依赖-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>

spring.factories文件:

根据springboot自动配置的过程,我们手动的配置了一个spring.factories用来设置自动加载类是谁

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.apesource.RedisAutoconfiguration

RedisProperties类:(定义主机和端口号)

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties {
    private String host="localhost";
    private int port=6379;

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }
}

        这里面的@ConfigurationProperties(prefix = "spring.redis")用于将外部配置文件,就比如 application.properties 或 application.yml中的配置参数绑定到这个类的字段上。

        host是Redis服务器的主机名,port是于存储 Redis 服务器的端口号。

RedisAutoConfiguration类:(配置类)

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.Jedis;

@Configuration
@EnableConfigurationProperties(RedisProperties.class)
public class RedisAutoconfiguration {
    //注入jedis
    @Bean
    public Jedis jedis(RedisProperties redisProperties){
        return new Jedis(redisProperties.getHost(), redisProperties.getPort());
    }
}

        加了@EnableConfigurationProperties(RedisProperties.class)注解用于对对 RedisProperties 配置属性类的支持。RedisProperties 是一个包含了 Redis 配置参数的类,通常包括主机名、端口等。通过这个注解,Spring Boot 可以将外部配置文件(如 application.properties 或 application.yml)中的相关配置映射到 RedisProperties 类的属性中,并自动实例化一个 RedisProperties 对象。

4、在测试模块中引入自定义的redis-starter依赖,测试获取JedisBean,操作redis

        <!--引入自定义的redis-spring-boot-starter模块-->
        <dependency>
            <groupId>com.apesource</groupId>
            <artifactId>redis-spring-boot-starter</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

properties.yml文件中自定义配置redis的主机和端口号

spring:
  redis:
    host: 127.0.0.1
    port: 6060

测试类:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import redis.clients.jedis.Jedis;

@SpringBootApplication
public class SpringbootStarter04Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext context=SpringApplication.run(SpringbootStarter04Application.class, args);
        Jedis bean1=context.getBean(Jedis.class);
        System.out.println(bean1);

    }
}

运行结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2051577.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用JQUERY请求数据出现500报错

我在写项目的时候遇到了一个问题&#xff0c;就是在存商品id的时候我将它使用了JSON.stringify的格式转换了&#xff01;&#xff01;&#xff01;于是便爆出了500这个错误&#xff01;&#xff01;&#xff01; 我将JSON.stringify的格式去除之后&#xff0c;它就正常显示了&a…

【数学建模】趣味数模问题——四人追逐问题

问题描述&#xff1a; 如图所示&#xff0c;在正方形ABCD的四个顶点各有一个人。在初始时刻 t0 时&#xff0c;四人同时出发&#xff0c;以匀速 v 沿顺时针方向朝下一个人移动。如果他们始终对准下一个人为目标行进&#xff0c;最终结果会如何&#xff1f;需要作出各自的运动轨…

路径规划 | 灰狼算法+B样条曲线优化无人机三维路径规划(Matlab)

目录 效果一览基本介绍程序设计参考文献 效果一览 基本介绍 灰狼算法B样条曲线优化无人机三维路径规划&#xff08;Matlab&#xff09; 群智能路径规划算法。三维灰狼算法&#xff08;GWO&#xff09;加B样条曲线优化的matlab代码。无人机&#xff08;UAV&#xff09;路径规划…

QT:安装软件

QT 介绍 QT是一个跨平台的C应用程序开发框架&#xff0c;具有广泛的应用领域和强大的功能。 定义&#xff1a;QT是一个跨平台的C图形用户界面应用程序框架&#xff0c;为开发者提供了建立艺术级图形界面所需的所有功能。 特点&#xff1a;QT具有短平快的优秀特质&#xff0c;即…

csrf漏洞(二)

本文仅作为学习参考使用&#xff0c;本文作者对任何使用本文进行渗透攻击破坏不负任何责任。 前言&#xff1a; 本文依靠phpstudy以及dvwa靶场进行操作&#xff0c;具体搭建流程参考&#xff1a;xss漏洞&#xff08;二&#xff0c;xss靶场搭建以及简单利用&#xff09; 前篇…

Godot关于3d射线投射的一些问题

首先你得把刚体模式激活如图否则将是空对象 为了区分其他坐标颜色园哥把射线设置成紫色以示区别 另外运行模式中貌似射线不可见只在调试模式中可见。最后查看调试器 成功碰撞一个名为主角的物体&#xff0c;也许都命中了但是方法只返回第一个命中的物体&#xff0c;吐槽一下&a…

场外个股期权如何发出行权指令?

场外期权行权指令也就是平仓指令的意思&#xff0c;一般场外个股期权交易有三种方式开仓和行权平仓指令&#xff0c;分别是市价&#xff0c;限价和半小时询价&#xff0c;跟普通股票的买卖和交易方式类似&#xff0c;唯一区别是手动发出场外个股期权的行权指令&#xff0c;下文…

Linux系统中的高级系统资源管理技术:systemd资源控制

在当今信息技术的快速发展中&#xff0c;服务器的性能管理和资源分配变得尤为重要。Linux操作系统以其灵活性和可定制性在服务器领域广受欢迎。而在Linux系统中&#xff0c;systemd资源控制作为一项重要的高级系统资源管理技术&#xff0c;为管理员提供了精细化控制和调整系统服…

STM32标准库学习笔记-2.GPIO

参考教程&#xff1a;【STM32入门教程-2023版 细致讲解 中文字幕】 标准库开发新建工程准备工作&#xff1a; 建立工程文件夹&#xff0c;Keil中新建工程&#xff0c;选择型号STM32F103C8T6工程文件夹里建立Start、Library、User等文件夹&#xff0c;复制固件库里面的文件到工…

【leetcode详解】实现一个魔法字典(思路详解 错误反思)

关于输入的解释&#xff1a; ‘ 输入 ’下方第一个列表是“调用函数”&#xff0c;第二个列表是“提供的字符串”&#xff0c;二者一一对应 如示例中buildDict对应[[“hello”, "leetcode"]]&#xff0c;即构建的字典包含 “hello” 和 "leetcode" 两个字…

基于laravel开发的开源交易所源码|BTC交易所/ETH交易所/交易所/交易平台/撮合交易引擎

开源交易所&#xff0c;基于Laravel开发的交易所 | BTC交易所 | ETH交易所 | 交易所 | 交易平台 | 撮合交易引擎。本项目有完整的撮合交易引擎源码、后台管理&#xff08;后端前端&#xff09;、前台&#xff08;交易页面、活动页面、个人中心等&#xff09; 特色&#xff1a;…

smbms

框架 数据库 项目如何搭建 考虑使不使用maven&#xff0c;依赖与jar包 项目搭建准备工作 搭建一个maven web项目配置tomcat测试项目是否能够跑起来导入项目中会遇到的jar包 //jsp、servlet、mysql驱动、jstl、stand.... <dependency><groupId>junit</groupI…

链表的删除 203、237、19 链表的遍历 430

203. 移除链表元素&#xff08;简单&#xff09; 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 解法一、递归 见代码 链表的定义具有递归的性质&#xff0c;所以遍历也可以以递归的方…

百度AI智能云依赖库OpenSSL库和Curl库及jsoncpp库安装

开发百度AI项目时&#xff0c;需要用到https协议&#xff0c;因此需要安装OpenSSl和curl库。 若只安装curl库&#xff0c;只支持http协议&#xff0c;不支持https协议。此外&#xff0c;还需要jsoncpp库&#xff0c;用以组包及解析与百度AI通信的json格式协议。 1.Ubuntu上安装…

修饰者模式

文章目录 1.简单介绍2.修饰器的优缺点3.模式结构3.案例分析4.总结5.装饰器模式和代理模式对比 1.简单介绍 装饰器模式&#xff08;Decorator Pattern&#xff09;也叫包装模式(Wrapper Pattern),是指在不改变原有对象的基础之上&#xff0c;将功能附加到对象上&#xff0c;提供…

【Linux —— 线程控制】

Linux —— 线程控制 进程和线程进程线程进程和线程的关系进程的优缺点Linux进程VS线程 Linux线程控制POSIX线程库创建线程线程等待线程终止线程分离 进程和线程 进程 进程是一个正在执行的程序实例&#xff0c;拥有独立的地址空间、数据段、代码段、堆栈以及系统资源&#xf…

大型语言模型(LLM)——直接偏好优化完整指南

概述 将大型语言模型 (LLM) 与人类价值观和偏好相结合是一项挑战。传统方法&#xff0c;例如 [从人类反馈中强化学习](&#xff08;RLHF&#xff09;通过整合人类输入来完善模型输出&#xff0c;为这一领域的研究铺平了道路。然而&#xff0c;RLHF 可能非常复杂且资源密集&…

CVE-2024-27198 和 CVE-2024-27199:JetBrains TeamCity 服务器的漏洞利用及其防护措施

引言 JetBrains TeamCity 作为一个广泛使用的持续集成和部署工具&#xff0c;其安全性备受关注。然而&#xff0c;最近披露的CVE-2024-27198和CVE-2024-27199两个漏洞揭示了该平台存在的重大安全隐患。这些漏洞允许攻击者通过绕过身份验证机制&#xff0c;创建未经授权的管理员…

Java代码基础算法练习-乘阶求和-2024.08.18

对应的源代码可以在我的 Gitee 仓库中找到&#xff0c;欢迎star~ [Gitee 仓库](https://gitee.com/yukongji/java-basic-algorithm) 任务描述&#xff1a; 求Sn1!2!3!4!5!…n!之值&#xff0c;其中n是一个数字(n<10)。 解决思路&#xff1a; 输入: 读取用户输入的 n 值。检查…

Java Sream中自定义Collector实现复杂数据收集方法

❃博主首页 &#xff1a; 「码到三十五」 &#xff0c;同名公众号 :「码到三十五」&#xff0c;wx号 : 「liwu0213」 ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a…