当前位置: 首页 > news >正文

SpringBoot如何做自动配置

目录

一、什么是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 实现类。

//MyImportSelectorpublic class MyImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {//目前字符串数组内容是写死的,未来可以设置在配置文件中动态加载return new String[]{"com.apesource.springbootenableother04.domain.User","com.apesource.springbootenableother04.domain.Student"};}
}//MyImportBeanDefinitionRegistrarpublic class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic 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 {@Beanpublic 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@Beanpublic 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.1port: 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.mrgr.cn/news/4451.html

相关文章:

  • Redis7基础篇(八)
  • QString检查字符串是否包含指定的子字符串的contains函数
  • vue-cron-builder一个相对简易的cron表达式生成插件UI管理javascript
  • 【Python】DrissionPage:一款轻量级的浏览器自动化和网页采集工具
  • 普元EOS-基于CriteriaEntity进行数据查询
  • 【Java】——Java程序实现学生成绩输入与等级划分
  • Nginx服务优化与防盗链
  • Java语言程序设计——篇十六
  • 企业人力资源管理建设方案和系统源码(岗位、组织、招聘、合同、绩效、五险、考勤、薪资、考试培训、人才发展)
  • 普元EOS-利用热更新(热启动)提高开发效率
  • 【JavaEE】MyBatis 实战指南:从 JDBC 到高效数据库操作的进阶教程
  • docker修改数据目录
  • 【Element Ui】在 vxe-table 中使用 el-cascader,退出编辑状态显示 label 值
  • 【bash】设置shell为英文输出
  • C语言实现Reactor
  • Python爬虫案例一:获取古诗文并按用户输入的作者名进行数据保存
  • 1088:分离整数的各个数
  • 【Qt笔记】Qt界面显示时间
  • 【C++二分查找 前缀和】1658. 将 x 减到 0 的最小操作数
  • go语言基础之goroutine与channel经典练习题