首页 > 其他分享 >springboot自动配置原理

springboot自动配置原理

时间:2024-08-21 19:24:05浏览次数:13  
标签:springboot 配置 public Bean 自动 注解 原理 class

 一、简介

        Spring Boot 的自动配置机制是其最核心的功能之一,它使得开发者能够快速地搭建应用程序而无需过多的手动配置。下面是对 Spring Boot 自动配置原理的一个概述:

1. Starter POMs (启动器)

Spring Boot 提供了一系列的 Starter POMs,这些 POMs 包含了构建应用所需的依赖项集合。例如,spring-boot-starter-web 包含了 Web 应用所需的所有依赖。

2. Auto-configuration (自动配置)

当引入 Starter POMs 时,Spring Boot 会自动查找并启用对应的自动配置类。自动配置类通常位于 org.springframework.boot.autoconfigure 包及其子包下,并带有 @EnableAutoConfiguration 注解。

关键组件
  • @SpringBootApplication:这是 Spring Boot 应用的主注解,它包含了 @SpringBootConfiguration@EnableAutoConfiguration 和 @ComponentScan。其中 @EnableAutoConfiguration 是启动自动配置的关键。
  • @EnableAutoConfiguration:该注解用来激活自动配置功能。
  • @AutoConfigurationPackage:此注解用于指定自动配置包的位置。
  • @Import:用于导入特定的自动配置类。
配置查找
  • spring.factories:在 META-INF/spring.factories 文件中定义了自动配置类的列表。例如,org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration 会被添加到 Spring 应用上下文中。
  • 条件注解:如 @ConditionalOnClass@ConditionalOnMissingBean@ConditionalOnProperty 等,用于控制自动配置类是否生效。

3. 自动配置类

每个自动配置类都负责为特定的组件或技术栈设置默认配置。这些类通常会检查应用上下文中的 Bean 是否存在,以及环境变量和配置文件中的属性值,从而决定是否激活某些配置。

4. 默认配置和覆盖

Spring Boot 会为很多常用的框架和技术提供默认的配置,但这些配置可以被覆盖。开发者可以通过编写自己的配置类,或者在 application.properties 或 application.yml 文件中修改属性值来覆盖默认配置。

5. 自定义自动配置

如果需要为某个第三方库提供自动配置支持,可以创建自己的自动配置类,并遵循上述的模式。通常需要在 META-INF/spring.factories 文件中注册新的自动配置类。

示例

假设我们使用了 spring-boot-starter-web,那么 Spring Boot 会自动寻找 DispatcherServlet 并配置相关的 Bean。例如,它会自动配置 Tomcat 嵌入式服务器、DispatcherServlet 以及相关组件。

这就是 Spring Boot 自动配置的基本原理。它大大简化了开发过程,使开发者能够专注于业务逻辑而不是繁琐的配置细节。

二、springboot自动配置

1.Condition

        Condition 是在 Spring 4.0 增加的条件判断功能,通过这个可以功能可以实现选择性的创建 Bean 操作。

测试:

思考: SpringBoot 是如何知道要创建哪个 Bean 的?比如 SpringBoot 是如何知道要创建 RedisTemplate 的?

导入坐标

       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>

ClassConditon.java

public class ClassCondition implements Condition {
    /**
     *
     * @param context 上下文对象。用于获取环境,IOC容器,ClassLoader对象
     * @param metadata 注解元对象。 可以用于获取注解定义的属性值
     * @return
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //1.需求: 导入Jedis坐标后创建Bean
        //思路:判断redis.clients.jedis.Jedis.class文件是否存在

        boolean flag = true;
        try {
            Class<?> cls = Class.forName("redis.clients.jedis.Jedis");
        } catch (ClassNotFoundException e) {
            flag = false;
        }
        return flag;

    }
}

UserConfig.java

@Configuration
public class UserConfig {

    //@Conditional中的ClassCondition.class的matches方法,返回true执行以下代码,否则反之
    @Bean
    @Conditional(value= ClassCondition.class)
    public User user(){
        return new User();
    }


}

User.java

public class User {

}

启动类

@SpringBootApplication
public class SpringbootCondition01Application {

    public static void main(String[] args) {

        //启动SpringBoot的应用,返回Spring的IOC容器
        ConfigurableApplicationContext context =  SpringApplication.run(SpringbootCondition01Application.class, args);
        //获取Bean,redisTemplate
        //情况1 没有添加坐标前,发现为空
        //情况2 有添加坐标前,发现有对象
//        Object redisTemplate = context.getBean("redisTemplate");
//        System.out.println(redisTemplate);

        /********************案例1********************/
        Object user = context.getBean("user");
        System.out.println(user);


    }

}

1. 没有添加坐标前,发现为空,报错

 2. 有添加坐标前,发现有对象

小结

自定义条件:
① 定义条件类:自定义类实现Condition接口,重写 matches 方法,在 matches 方法中进行逻辑判 断,返回 boolean值 。
matches 方法两个参数:
context:上下文对象,可以获取属性值,获取类加载器,获取BeanFactory等。
metadata:元数据对象,用于获取注解属性。
② 判断条件: 在初始化Bean时,使用 @Conditional(条件类.class)注解

ConditionalOnProperty:判断配置文件中是否有对应属性和值才初始化Bean

ConditionalOnClass:判断环境中是否有对应字节码文件才初始化Bean

ConditionalOnMissingBean:判断环境中没有对应Bean才初始化

Bean ConditionalOnBean:判断环境中有对应Bean才初始化Bean

可以查看RedisAutoConfiguration类说明以上注解使用

2.@Enable注解

SpringBoot中提供了很多Enable开头的注解,这些注解都是用于动态启用某些功能的。而其底层原理是使用@Import注解导入一些配置类,实现Bean的动态加载  

@Import注解

@Enable底层依赖于@Import注解导入一些类,使用@Import导入的类会被Spring加载到IOC容器中。 而@Import提供4中用法:

① 导入Bean

② 导入配置类

③ 导入 ImportSelector 实现类。一般用于加载配置文件中的类

④ 导入 ImportBeanDefinitionRegistrar 实现类。

思考 SpringBoot 工程是否可以直接获取jar包中定义的Bean?

 

测试:

创建两个类springboot_enable和springboot_other

其中 springboot-enable-other用于模拟其他jar包

在springboot_enable中导入spring_enable_other坐标

<!--导入坐标-->
        <dependency>
            <groupId>com.apesource</groupId>
            <artifactId>springboot-enable_other-04</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

MyImportBeanDefinitionRegistrar.java

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

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

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

    }
}

MyImportSelector.java

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

UserConfig.java

@Configuration
public class UserConfig {

    @Bean
    public User userTest() {
        return new User();
    }


}

Student.java

public class Student {
}

User.java

public class User {
}

测试类

@SpringBootApplication
//@Import(User.class)
//@Import(UserConfig.class)
//@Import(MyImportSelector.class)
@Import({MyImportBeanDefinitionRegistrar.class})
//@EnableCaching
//@EnableAsync
public class SpringbootEnable03Application {



    public static void main(String[] args) {

        ConfigurableApplicationContext context =  SpringApplication.run(SpringbootEnable03Application.class, args);
        /**
         * Import4中用法:
         *  1. 导入Bean
         *  2. 导入配置类
         *  3. 导入ImportSelector的实现类
         *      查看ImportSelector接口源码
         *          String[] selectImports(AnnotationMetadata importingClassMetadata);
         *          代表将“字符串数组”中的的类,全部导入spring容器
         *  4. 导入ImportBeanDefinitionRegistrar实现类
         *
         */
//        User user = context.getBean(User.class);
//        System.out.println(user);
//
//        Student student = context.getBean(Student.class);
//        System.out.println(student);

        User user = (User) context.getBean("user");
        System.out.println(user);


    }

}

3.@EnableAutoConfiguration 注解 

主启动类


//@SpringBootApplication 来标注一个主程序类
//说明这是一个Spring Boot应用
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
//以为是启动了一个方法,没想到启动了一个服务
SpringApplication.run(SpringbootApplication.class, args);
}
}

@SpringBootApplication注解内部

@ComponentScan

这个注解在Spring中很重要 ,它对应XML配置中的元素。

作用:自动扫描并加载符合条件的组件或者bean , 将这个bean定义加载到IOC容器中

@SpringBootConfiguration

作用:SpringBoot的配置类 ,标注在某个类上 , 表示这是一个SpringBoot的配置类;

@AutoConfigurationPackage :自动配置包  

@EnableAutoConfiguration开启自动配置功能 

以前我们需要自己配置的东西,而现在SpringBoot可以自动帮我们配置 ;@EnableAutoConfiguration 告诉SpringBoot开启自动配置功能,这样自动配置才能生效;

@Import({AutoConfigurationImportSelector.class}) :给容器导入组件 ;

AutoConfigurationImportSelector :自动配置导入选择器,给容器中导入一些组件

AutoConfigurationImportSelector.class
         ↓
    selectImports方法
         ↓
this.getAutoConfigurationEntry(annotationMetadata)方法
         ↓
this.getCandidateConfigurations(annotationMetadata, attributes)方法
         ↓
方法体:
 List<String> configurations = 
SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass
(), this.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;
 ↓
在所有包名叫做autoConfiguration的包下面都有META-INF/spring.factories文件

总结原理

@EnableAutoConfiguration 注解内部使用 @Import(AutoConfigurationImportSelector.class) 来加载配置类。

配置文件位置:META-INF/spring.factories,该配置文件中定义了大量的配置类,当 SpringBoot 应用启动时,会自动加载这些配置类,初始化Bean

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

标签:springboot,配置,public,Bean,自动,注解,原理,class
From: https://blog.csdn.net/xzcxzc1q/article/details/141288738

相关文章

  • 一键关闭windows10自动更新
    win10这个系统,别的方面还算不错的,但我当初坚守WIN7是因为win7老实有自主权,而win10时不时的来一个更新,而且常常玩自动更新,一个误操作就让自己半天心血没搞没。所以我对win10一直是很嫌弃的,但人生有时候确实不得已,就像我最初要坚守xp,结果不得不使用多年的win7,而现在win7也已......
  • 基于SpringBoot+Vue的实验室排课系统设计与实现(2025年毕业项目-源码+论文+部署讲解等)
    文章目录1.前言2.详细视频演示3.论文参考4.项目运行截图5.技术框架5.1后端采用SpringBoot框架5.2前端框架Vue6.可行性分析7.系统测试7.1系统测试的目的7.2系统功能测试8.数据库表设计9.代码参考10.数据库脚本11.作者推荐项目12.为什么选择我?13.获取源......
  • 软件测试-web自动化测试-前期环境搭建
    记录学习笔记web端自动化测试也就是网页自动化测试。主要在PyCharm软件里编写代码,前期需要准备python+selenium的基础环境搭建。1、下载安装python,下载最新版检查环境:在cmd里python -v和pip -v可以正常出现。√2、PyCharm安装,下载社区免费版直接next安装即可,打开软......
  • Spring Boot 应用案例:打造股票价格自动通知平台
    在本篇博文中,我们将构建一个简单的SpringBoot应用来演示如何创建一个股票价格更新系统,并在股票价格变动时自动通知订阅用户。这个示例将涵盖SpringBoot的核心功能,包括Web模块、数据持久化、消息队列以及简单的用户订阅机制。项目结构和依赖首先,我们需要创建一个新的Spring......
  • Python自动化脚本学习整理
     10个常用Python自动化脚本https://blog.csdn.net/csdn1561168266/article/details/135757528?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522172422930716800184162692%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=1724229307168......
  • vue3中script标签的setup实现原理
    概述当vue3新建组件时,我们有两种选择选项式和组合式,如下所示传统方式<script>import{ref}from"vue";exportdefault{setup(){constcount=ref(0);consthandleClick=()=>{count.value++;};return{count,handleClick......
  • springboot+vue服装搭配推荐系统【程序+论文+开题】-计算机毕业设计
    系统程序文件列表开题报告内容研究背景随着电子商务的蓬勃发展和个性化消费趋势的兴起,服装行业正经历着前所未有的变革。在海量商品面前,消费者往往面临选择困难,尤其是在服装搭配方面,如何根据个人喜好、身形特点以及场合需求快速找到最合适的搭配方案,成为众多消费者的迫切需......
  • springboot+vue扶贫助农与产品合作系统【程序+论文+开题】-计算机毕业设计
    系统程序文件列表开题报告内容研究背景在当前全球减贫事业与乡村振兴战略的双重背景下,扶贫助农已成为社会各界关注的焦点。随着信息技术的飞速发展,特别是互联网与电子商务的普及,为扶贫工作开辟了新路径。然而,农村地区由于信息不对称、物流成本高、销售渠道有限等问题,优质农......
  • springboot+vue峰数公司医疗设备管理系统【程序+论文+开题】-计算机毕业设计
    系统程序文件列表开题报告内容研究背景随着医疗技术的飞速发展,医疗设备的种类与数量日益增长,对医院运营管理提出了更高要求。峰数公司作为一家专注于医疗健康领域的企业,其业务范围广泛,涵盖从高端医疗设备供应到后期维护的全方位服务。然而,在传统管理模式下,设备信息散乱、管......
  • springboot+vue分类学科竞赛管理系统-后台2023【程序+论文+开题】-计算机毕业设计
    系统程序文件列表开题报告内容研究背景随着教育改革的深入和素质教育的全面推广,学科竞赛作为培养学生创新能力、实践能力和团队协作精神的重要途径,其重要性日益凸显。然而,传统的手工管理方式在应对日益增长的竞赛数量、复杂的竞赛分类及庞大的参赛学生信息时显得力不从心。......