手写模拟Spring Boot自动配置功能

引言

随着微服务架构的兴起,Spring Boot作为一种快速开发框架,因其简化了Spring应用的初始搭建和开发过程,受到了广大开发者的青睐。自动配置作为Spring Boot的核心特性之一,大大减少了手动配置的工作量,提高了开发效率。本文将从背景历史、业务场景、功能点、底层原理等方面详细介绍Spring Boot的自动配置功能,并通过Java代码手写模拟这一功能,为资深Java工程师提供一个深入理解和实践的机会。

一、背景历史

Spring Boot的起源与发展

Spring Boot最初基于Spring 4.0设计,由Pivotal公司提供。其诞生背景是Spring框架在开发过程中存在大量的XML配置以及复杂的依赖管理,导致开发效率低下。为了解决这一问题,Pivotal团队在2013年开始研发Spring Boot项目,并于2014年4月发布了Spring Boot 1.0.0版本。此后,Spring Boot不断迭代更新,引入了更多便捷的功能和性能优化,成为了Java开发中构建微服务应用的首选框架之一。

自动配置的引入

自动配置是Spring Boot的核心特性之一,它通过推断应用所需的配置,自动为应用程序注册合适的Bean,从而简化了繁琐的手动配置过程。自动配置的引入,使得开发者无需再编写大量的XML或Java配置文件,只需关注业务逻辑的实现即可。

二、业务场景

微服务架构

在微服务架构中,每个服务都是一个独立的应用程序,需要快速搭建和部署。Spring Boot的自动配置功能使得开发者可以快速创建一个功能完整的微服务应用,无需关注底层框架的配置细节,从而提高了开发效率。

Web应用程序开发

对于Web应用程序开发而言,Spring Boot提供了丰富的Web开发特性,如RESTful API、WebSocket等。通过自动配置,开发者可以快速搭建一个Web应用,无需手动配置Servlet容器、Spring MVC等组件。

数据访问与缓存管理

在数据访问和缓存管理方面,Spring Boot集成了Spring Data JPA、Spring Data MongoDB等数据访问模块,以及Ehcache、Redis等缓存管理工具。通过自动配置,开发者可以方便地进行数据库操作和访问,以及提高应用程序的性能和可伸缩性。

三、功能点

自动配置

Spring Boot的自动配置功能能够根据项目的依赖和环境自动设置Spring应用程序,减少了手动配置的复杂度。例如,当项目中引入了spring-boot-starter-web依赖时,Spring Boot会自动配置Tomcat和Spring MVC等组件。

起步依赖

起步依赖是Spring Boot提供的一组预定义的依赖集合,包含了常用的库和框架的依赖关系。开发者只需在项目中添加相应的起步依赖,即可快速构建出一个功能完整的应用程序。

嵌入式服务器

Spring Boot内置了Tomcat、Jetty和Undertow等多个服务器,使得应用程序可以打包成一个可执行的JAR文件,直接运行而无需外部Web服务器。

外部化配置

Spring Boot支持外部化配置,允许开发者通过配置文件、环境变量等方式灵活地配置应用程序。这使得应用程序的配置更加灵活和可维护,便于在不同环境中进行部署和配置。

四、底层原理

核心组件与注解

@SpringBootApplication

@SpringBootApplication是一个复合注解,它结合了@Configuration、@EnableAutoConfiguration和@ComponentScan三个注解的功能。这个注解通常被用在主启动类上,用于开启Spring Boot的自动配置和组件扫描。

  • @Configuration:表示该类是一个配置类,相当于传统的Spring XML配置文件。在配置类中,可以通过@Bean注解来定义和注册Bean。
  • @EnableAutoConfiguration:告诉Spring Boot根据添加的jar依赖来自动配置项目。例如,如果添加了spring-boot-starter-web依赖,Spring Boot会自动配置Tomcat和Spring MVC。
  • @ComponentScan:让Spring Boot自动扫描当前包及其子包中的@Component、@Repository、@Service、@Controller等注解的类,并将它们注册为Bean。
SpringApplication类

SpringApplication类是Spring Boot的启动类,它负责启动整个Spring应用上下文。在main方法中,通过调用SpringApplication.run(Application.class, args)方法来启动Spring Boot应用。

启动流程

Spring Boot的启动流程可以概括为以下几个步骤:

  1. 读取配置文件:SpringBoot默认会在resources文件夹下读取application.properties或application.yml配置文件,这些配置文件包含了应用的各种配置信息。
  2. 初始化Spring应用上下文:在main方法中,通过调用SpringApplication.run(Application.class, args)方法来初始化Spring应用上下文。这个过程包括装配参数和环境、创建ApplicationContext、注册各种组件等。
  3. 自动配置:SpringBoot会根据添加的jar依赖和配置文件中的信息来自动配置项目。这个过程是通过@EnableAutoConfiguration注解来实现的,它会根据类路径中的jar依赖为项目进行自动配置。
  4. 组件扫描与注册:@ComponentScan注解会让SpringBoot自动扫描当前包及其子包中的注解类,并将它们注册为Bean。这些Bean会被存储在Spring的IoC容器中,供后续使用。
  5. 发布事件:在SpringBoot启动过程中,会发布多个事件,如ApplicationStartedEvent、ApplicationEnvironmentPreparedEvent、ApplicationPreparedEvent和ApplicationReadyEvent等。这些事件可以被自定义的监听器捕获和处理,以实现一些自定义的启动逻辑。

自动配置的实现机制

Spring Boot的自动配置是通过Spring框架的条件化注解实现的。具体来说,Spring Boot会根据类路径中的依赖项、已声明的Bean以及其他上下文信息,自动为应用程序注册合适的Bean。

条件化注解

Spring Boot提供了多个条件化注解,用于在特定条件下启用或禁用自动配置:

  • @ConditionalOnClass:当类路径中存在指定的类时,才会启用相应的自动配置。
  • @ConditionalOnMissingBean:当容器中没有指定的Bean时,才会应用配置。
  • @ConditionalOnProperty:根据配置文件中的某个属性是否启用,决定是否加载该配置。
自动配置类

自动配置类通常位于spring-boot-autoconfigure模块中,它们会根据配置文件和类路径中的jar依赖来自动配置项目的各种组件。例如,DataSourceAutoConfiguration类会根据类路径中的数据库驱动以及配置文件中的数据库连接信息自动配置数据源。

spring.factories文件

META-INF/spring.factories文件是Spring Boot自动配置的重要部分,它定义了自动配置类的加载路径。Spring Boot在启动时会扫描此文件中的配置,并将其加载到Spring容器中。

五、手写模拟Spring Boot自动配置功能

下面,我们将通过Java代码手写模拟Spring Boot的自动配置功能。

1. 定义自动配置属性类

首先,我们定义一个自动配置属性类,用于存储配置信息。这个类将使用@ConfigurationProperties注解进行标记,以便Spring Boot能够将其属性与配置文件中的值进行绑定。

java复制代码
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "my.config")
public class MyConfigProperties {
private String name = "defaultName";
private int age = 18;
// Getter and Setter methods
public String getName() {
return name;}
public void setName(String name) {
this.name = name;}
public int getAge() {
return age;}
public void setAge(int age) {
this.age = age;}
}

2. 创建自动配置类

接下来,我们创建一个自动配置类,该类将使用条件化注解来判断是否需要自动配置某个Bean。

java复制代码
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConditionalOnClass(MyConfigProperties.class)
@EnableConfigurationProperties(MyConfigProperties.class)
public class MyAutoConfiguration {
private final MyConfigProperties properties;
public MyAutoConfiguration(MyConfigProperties properties) {
this.properties = properties;}
@Bean
@ConditionalOnMissingBean
public MyService myService() {
return new MyService(properties.getName(), properties.getAge());}
}

3. 定义服务类

然后,我们定义一个服务类,该类将作为自动配置的Bean。

java复制代码
public class MyService {
private String name;
private int age;
public MyService(String name, int age) {
this.name = name;
this.age = age;}
public String saySomething() {
return "My name is " + name + ", and I am " + age + " years old.";}
}

4. 在META-INF/spring.factories文件中声明自动配置类

最后,我们需要在META-INF/spring.factories文件中声明自动配置类,以便Spring Boot能够自动加载它。

复制代码
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyAutoConfiguration

5. 编写主应用类

现在,我们可以编写主应用类来启动Spring Boot应用,并测试自动配置功能。

java复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MySpringBootApplication {
@Autowired
private MyService myService;
public static void main(String[] args) {SpringApplication.run(MySpringBootApplication.class, args);}
@Bean
public CommandLineRunner commandLineRunner() {
return args -> System.out.println(myService.saySomething());}
}

6. 编写配置文件

在src/main/resources目录下创建application.properties文件,并添加以下配置信息:

复制代码
my.config.name=myName
my.config.age=30

7. 运行应用

现在,我们可以运行主应用类MySpringBootApplication,观察自动配置功能是否生效。如果一切配置正确,控制台将输出以下信息:

复制代码
My name is myName, and I am 30 years old.

这表明MyService Bean已经成功通过自动配置创建,并且其属性值与配置文件中的值一致。

六、总结

通过本文的介绍,我们深入了解了Spring Boot自动配置的背景历史、业务场景、功能点以及底层原理。同时,我们还通过Java代码手写模拟了Spring Boot的自动配置功能,展示了如何实现一个简单的自动配置类。希望本文能够帮助资深Java工程师更好地理解和应用Spring Boot的自动配置功能,提高开发效率和质量。

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

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

相关文章

Linux性能优化之火焰图的起源

Linux火焰图的起源与性能优化专家 Brendan Gregg 密切相关,他在 2011 年首次提出这一工具,用于解决性能分析过程中可视化和数据解读的难题。 1. 背景:性能优化的需求 在现代计算中,性能优化往往需要对程序执行中的热点和瓶颈进行…

【论文精读】GOT-OCR2.0源码论文——打破传统OCR流程的多模态视觉-语言大模型架构:预训练VitDet 视觉模型+ 阿里通义千问Qwen语言模型

作为本系列的开篇文章,首先定下本系列的整体基调。论文精读系列,旨在记录研读深度学习、强化学习相关论文的个人心得和理解,仅供参考,欢迎指正错误和研究探讨。 所有文章只会摘选论文部分进行分析,且不一定按原文行文顺…

动态规划之股票系列

123. 买卖股票的最佳时机 III 188. 买卖股票的最佳时机 IV 309. 买卖股票的最佳时机含冷冻期 1.AC代码: class Solution {public int maxProfit(int[] prices) {int nprices.length;int[][] dpnew int[n][5];dp[0][1]-prices[0];dp[0][3]-prices[0];for(int i1;i<n;i){/…

使用 Qt 实现基于海康相机的图像采集和显示系统(不使用外部视觉库,如Halcon\OpenCv)[工程源码联系博主索要]

本文将梳理一个不借助外部视觉库&#xff08;如 OpenCV/Halcon&#xff09;的海康相机图像采集和显示 Demo。该程序直接使用 Qt GUI 来显示图像。通过海康 MVS SDK 实现相机的连接、参数设置、图像采集和异常处理等功能&#xff0c;并通过 Qt 界面展示操作结果。 1. 功能概述 …

在Ubuntu22.04上源码构建ROS noetic环境

Ubuntu22.04上源码构建ROS noetic 起因准备环境创建工作目录并下载源码安装编译依赖包安装ros_comm和rosconsole包的两个补丁并修改pluginlib包的CMakeLists的编译器版本编译安装ROS noetic和ros_test验证 起因 最近在研究VINS-Mono从ROS移植到ROS2&#xff0c;发现在编写feat…

C++——类和对象(part2)

前言 本篇博客继续为大家介绍类与对象的知识&#xff0c;承接part1的内容&#xff0c;本篇内容是类与对象的核心内容&#xff0c;稍微有些复杂&#xff0c;如果你对其感兴趣&#xff0c;请继续阅读&#xff0c;下面进入正文部分。 1. 类的默认成员函数 默认成员函数就是用户…

matlab实现主成分分析方法图像压缩和传输重建

原创 风一样的航哥 航哥小站 2024年11月12日 15:23 江苏 为了研究图像的渐进式传输技术&#xff0c;前文提到过小波变换&#xff0c;但是发现小波变换非常适合传输缩略图&#xff0c;实现渐进式传输每次传输的数据量不一样&#xff0c;这是因为每次变换之后低频成分大约是上一…

【HarmonyOS】鸿蒙系统在租房项目中的项目实战(二)

从今天开始&#xff0c;博主将开设一门新的专栏用来讲解市面上比较热门的技术 “鸿蒙开发”&#xff0c;对于刚接触这项技术的小伙伴在学习鸿蒙开发之前&#xff0c;有必要先了解一下鸿蒙&#xff0c;从你的角度来讲&#xff0c;你认为什么是鸿蒙呢&#xff1f;它出现的意义又是…

Scala-字符串(拼接、printf格式化输出等)-用法详解

Scala 一、 使用 号连接字符串 在 Scala 中&#xff0c; 运算符实际上会调用 String 类的 concat 方法或者使用字符串的加法操作&#xff0c;生成一个新的字符串。 字符串是不可变的&#xff0c;每次拼接都会创建一个新的字符串。 Mr. yuTips&#xff1a; 性能相对较差&…

ISCTF2024

ezlogin 源码审计 先审源码,纯js题 const express require(express); const app express(); const bodyParser require(body-parser); var cookieParser require(cookie-parser); var serialize require(node-serialize); app.use(bodyParser.urlencoded({ e…

Mac Java 使用 tesseract 进行 ORC 识别

在 Java 开发中使用图片转文字时&#xff0c;难免会遇到问题&#xff0c;比如我使用 Mac (M1 芯片) 系统进行开发&#xff0c;就出现报错。 博主博客 https://blog.uso6.comhttps://blog.csdn.net/dxk539687357 一、直接使用 1. 使用 brew 进行安装 brew install tesseract…

策略模式-策略模式在不同支付工具中的应用

策略模式中主要有以下角色 抽象策略接口 具体策略实现 1. 定义策略接口 /*** @desc 支付抽象类**/ public interface Pay {/*** 缓存支付方式和对应的支付策实现对象*/Map<String, Pay> payMap = new HashMap<>();public String payment(); } 2. 定义AliPay具体…

使用真实 Elasticsearch 进行更快的集成测试

作者&#xff1a;来自 Elastic Piotr Przybyl 了解如何使用各种数据初始化和性能改进技术加快 Elasticsearch 的自动化集成测试速度。 在本系列的第 1 部分中&#xff0c;我们探讨了如何编写集成测试&#xff0c;让我们能够在真实的 Elasticsearch 环境中测试软件&#xff0c;并…

MySQL:联合查询(2)

首先写一个三个表的联合查询 查询所有同学的每门课成绩&#xff0c;及同学的个人信息 1.我们首先要确定使用哪些表 学生表&#xff0c;课程表&#xff0c;成绩表 2.取笛卡尔积 select * from score,student,course; 3. 确定表与表之间的联合条件 select * from score,stud…

Vue3学习笔记(下)

文章目录 Vue3学习笔记&#xff08;下&#xff09;组合式API下的父子通信父传子子传父 模板引用defineExpose()provide和injectvue3新特性 - defineOptionsvue3新特性 - defineModelPiniaPinia异步写法 Vue3学习笔记&#xff08;下&#xff09; 组合式API下的父子通信 父传子…

【循环测试试题3】小X与数字三角形

题目描述 读入一个正整数n&#xff0c;输出一个n行的数字三角形。 输入 一行一个正整数n&#xff0c;2<n<10。 输出 共n行&#xff0c;第i行包含i个正整数&#xff0c;每个整数占五列。 样例输入 5 样例输出 12 34 5 67 8 9 1011 12 13 14 …

CNN神经网络

CNN 一 基本概述二 基础知识三 经典案例 今天和大家聊聊人工智能中的神经网络模型相关内容。神经网络内容庞大,篇幅有限本文主要讲述其中的CNN神经网络模型和一些基本的神经网络概念。 一 基本概述 深度学习(Deep Learning)特指基于深层神经网络模型和方法的机器学习。它是在…

React中事件绑定和Vue有什么区别?

1. 绑定方式 React&#xff1a;使用jsx语法&#xff0c;通过属性绑定事件。Vue&#xff1a;使用指令&#xff08;如v-on&#xff09;在模板中直接绑定事件。 2. 事件处理 React&#xff1a;通过合成事件系统封装原生事件&#xff0c;提供统一的API。Vue&#xff1a;直接使用…

MySQL —— MySQL基础概念与常用功能介绍

文章目录 基本概念数据类型数据类型分类 约束主键约束&#xff08;PRIMARY KEY&#xff09;外键约束&#xff08;FOREIGN KEY&#xff09;使用非空约束&#xff08;not null&#xff09;使用唯一性约束&#xff08;UNIQUE&#xff09;使用默认约束&#xff08;DEFAULT&#xff…

如何在react中使用react-monaco-editor渲染出一个编辑器

一、效果展示 二、基于vite配置 1.首先安装react-monaco-editor和monaco-editor包 npm add react-monaco-editor npm i monaco-editor 2.其次创建一个单独的文件&#xff08;此处是tsx、直接用app或者jsx也行&#xff09; import { useState, useEffect } from react impo…