0


SpringBoot如何做自动配置

一、什么是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模块中初始化Jedis的Bean,并定义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依赖,测试获取Jedis的Bean,操作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);

    }
}

运行结果:

标签: spring boot 后端 java

本文转载自: https://blog.csdn.net/Z_DOUBLE_Y/article/details/141304543
版权归原作者 Z_DOUBLE_Y 所有, 如有侵权,请联系我们删除。

“SpringBoot如何做自动配置”的评论:

还没有评论