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 实现类。

//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);

    }
}

运行结果:

  • 16
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值