拆解Spring boot:Springboot为什么如此丝滑而简单?源码剖析解读自动装配

这篇具有很好参考价值的文章主要介绍了拆解Spring boot:Springboot为什么如此丝滑而简单?源码剖析解读自动装配。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

拆解Spring boot:Springboot为什么如此丝滑而简单?源码剖析解读自动装配,《Spring 狂野之旅:底层原理高级进阶》 🚀,spring,spring boot,后端

🎉🎉欢迎光临,终于等到你啦🎉🎉

🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀

🌟持续更新的专栏《Spring 狂野之旅:从入门到入魔》 🚀

本专栏带你从Spring入门到入魔 

这是苏泽的个人主页可以看到我其他的内容哦👇👇

努力的苏泽http://suzee.blog.csdn.net/

 文章来源地址https://www.toymoban.com/news/detail-842671.html


 

springboot帮我们做了什么

一个字--自动!

通常搭建一个基于spring的web应用,我们需要做以下工作:

1、pom文件中引入相关jar包,包括spring、springmvc、redis、mybaits、log4j、mysql-connector-java 等等相关jar ...

2、配置web.xml,Listener配置、Filter配置、Servlet配置、log4j配置、error配置 ...

3、配置数据库连接、配置spring事务

4、配置视图解析器

5、开启注解、自动扫描功能

6、配置完成后部署tomcat、启动调试

......

这些都是Spring boot在背后默默为我们做的工作

那 有没有想过为什么? 

本文给大家来解读Spring的源码 拆解他的自动配置 一步一步解释为什么Springboot为何那么强大

 

 

进入他的细节源码之前 首先关注 ---架构

拆解Spring boot:Springboot为什么如此丝滑而简单?源码剖析解读自动装配,《Spring 狂野之旅:底层原理高级进阶》 🚀,spring,spring boot,后端

解读SpringBootApplication

@Target(ElementType.TYPE)            // 注解的适用范围,其中TYPE用于描述类、接口(包括包注解类型)或enum声明
@Retention(RetentionPolicy.RUNTIME)  // 注解的生命周期,保留到class文件中(三个生命周期)
@Documented                          // 表明这个注解应该被javadoc记录
@Inherited                           // 子类可以继承该注解
@SpringBootConfiguration             // 继承了Configuration,表示当前是注解类
@EnableAutoConfiguration             // 开启springboot的注解功能,springboot的四大神器之一,其借助@import的帮助
@ComponentScan(excludeFilters = {    // 扫描路径设置(具体使用待确认)
        @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
...
}

@Configuration

这里的@Configuration 对我们来说不陌生,它就是 JavaConfig 形式的 Spring Ioc 容器的配置类使用的那个@Configuration,SpringBoot 社区推荐使用基于 JavaConfig 的配置形式,所以,这里的启动类标注了@Configuration 之后,本身其实也是一个 IoC 容器的配置类。 举几个简单例子回顾下,XML 跟 config 配置方式的区别:

表达形式层面 基于 XML 配置的方式是这样:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
       default-lazy-init="true">
    <!--bean定义-->
</beans>

而基于 JavaConfig 的配置方式是这样:

@Configuration
public class MockConfiguration{
    //bean定义
}

任何一个标注了@Configuration 的 Java 类定义都是一个 JavaConfig 配置类。

注册 bean 定义层面 基于 XML 的配置形式是这样:

<bean id="mockService" class="..MockServiceImpl">
    ...
</bean>

而基于 JavaConfig 的配置形式是这样的:

@Configuration
public class MockConfiguration{
    @Bean
    public MockService mockService(){
        return new MockServiceImpl();
    }
}

任何一个标注了@Bean 的方法,其返回值将作为一个 bean 定义注册到 Spring 的 IoC 容器,方法名将默认成该 bean 定义的 id。

表达依赖注入关系层面 为了表达 bean 与 bean 之间的依赖关系,在 XML 形式中一般是这样:

<bean id="mockService" class="..MockServiceImpl">
    <propery name ="dependencyService" ref="dependencyService" />
</bean>

<bean id="dependencyService" class="DependencyServiceImpl"></bean>

而基于 JavaConfig 的配置形式是这样的:

@Configuration
public class MockConfiguration{
    @Bean
    public MockService mockService(){
        return new MockServiceImpl(dependencyService());
    }

    @Bean
    public DependencyService dependencyService(){
        return new DependencyServiceImpl();
    }
}

@ComponentScan:


@ComponentScan注解用于指定Spring容器扫描组件的基础包路径。它会自动扫描指定包及其子包下的类,并将被@Component及其派生注解标注的类识别为Spring的组件,将其实例化并纳入容器管理。

// 在包com.example中定义了两个被@Component注解标记的类:UserService和UserRepository

// UserService.java
package com.example;

import org.springframework.stereotype.Component;

@Component
public class UserService {
    // ...
}

// UserRepository.java
package com.example;

import org.springframework.stereotype.Component;

@Component
public class UserRepository {
    // ...
}

// AppConfig.java
package com.example;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.example") // 指定扫描的基础包路径
public class AppConfig {
    // 配置其他的Bean
}

@ComponentScan的原理可以从源代码的角度来解释。在Spring的源代码中,@ComponentScan注解被解析为一个Bean扫描器。当Spring容器启动时,扫描器会根据指定的包路径,将带有@Component及其派生注解的类解析为BeanDefinition对象,并注册到BeanFactory中。这样,Spring容器就知道这些类是组件,并可以对其进行实例化和管理。

 

@EnableAutoConfiguration:


@EnableAutoConfiguration注解用于启用Spring Boot的自动配置功能。它会根据项目的依赖和配置,自动加载和配置一系列的Spring Bean,简化了项目的配置过程。

@EnableAutoConfiguration的原理可以从源代码的角度来解释。在Spring Boot的源代码中,@EnableAutoConfiguration注解被解析为一个自动配置处理器。当Spring Boot应用启动时,处理器会根据classpath下的META-INF/spring.factories文件中的配置,加载并执行一系列的自动配置类。这些自动配置类根据约定和条件,自动创建和配置相应的Bean对象,完成项目的自动化配置。

Import(AutoConfigurationImportSelector.class)注解:

拆解Spring boot:Springboot为什么如此丝滑而简单?源码剖析解读自动装配,《Spring 狂野之旅:底层原理高级进阶》 🚀,spring,spring boot,后端

图中看出 AutoConfigurationImportSelector 继承了 DeferredImportSelector 继承了 ImportSelector

ImportSelector有一个方法为:selectImports。

@Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }
        AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
                .loadMetadata(this.beanClassLoader);
        AnnotationAttributes attributes = getAttributes(annotationMetadata);
        List<String> configurations = getCandidateConfigurations(annotationMetadata,
                attributes);
        configurations = removeDuplicates(configurations);
        Set<String> exclusions = getExclusions(annotationMetadata, attributes);
        checkExcludedClasses(configurations, exclusions);
        configurations.removeAll(exclusions);
        configurations = filter(configurations, autoConfigurationMetadata);
        fireAutoConfigurationImportEvents(configurations, exclusions);
        return StringUtils.toStringArray(configurations);
    }

AutoConfigurationImportSelector是Spring Boot内部的一个选择器类,它会根据项目的依赖和配置,选择要自动配置的类。该选择过程是基于条件注解(如@ConditionalOnClass、@ConditionalOnProperty等)进行的,只有满足条件的自动配置类才会被选择。

 

@AutoConfigurationPackage

// 在包com.example中定义了一个主配置类ApplicationConfig

// ApplicationConfig.java
package com.example;

import org.springframework.boot.autoconfigure.AutoConfigurationPackage;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@AutoConfigurationPackage // 标注了@AutoConfigurationPackage注解
public class ApplicationConfig {
    // 主配置类的内容
    // ...
}

当Spring Boot启动时,它会扫描并解析主配置类ApplicationConfig。在解析过程中,Spring Boot会检测到@AutoConfigurationPackage注解,并执行相应的处理。

@AutoConfigurationPackage注解被解析为一个特殊的Bean定义处理器。处理器会读取主配置类ApplicationConfig的包路径(com.example),并将该包路径注册到Spring的BeanFactory中。

注册完成后,Spring容器会将com.example包及其子包作为组件扫描的范围。这意味着Spring会扫描该包下的所有类,并根据条件注解(如@ConditionalOnClass@ConditionalOnMissingBean等)来决定是否自动配置相应的Bean。

通过将主配置类所在的包及其子包作为自动配置的包,我们可以确保自动配置类能够正确地扫描和应用到我们的应用程序中。

 

 

 

到了这里,关于拆解Spring boot:Springboot为什么如此丝滑而简单?源码剖析解读自动装配的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Redis为什么能如此之快

    Redis,一个以超高的性能和强大 的数据结构功能著称的内存数据库,在处理各种复杂数据操作时,速度却能达到惊人的水平。那么,Redis为什么能如此之快呢?今天,我们就来深入解析一下Redis的线程模型,揭开这个问题的神秘面纱。 在探讨Redis的线程模型之前,我们首先需要

    2024年02月12日
    浏览(36)
  • Hadoop为什么如此流行——史上最详解

    作者:禅与计算机程序设计艺术 Hadoop是一个开源的分布式计算框架,其出现主要是为了解决海量数据的存储、计算、分析、和处理问题。随着互联网的数据量不断增加,分布式系统越来越普及,Hadoop也越来越受到青睐。它具备高容错性、高可靠性、弹性扩展等特性,能够适应

    2024年02月08日
    浏览(43)
  • 面试官问:kafka为什么如此之快?

    天下武功,唯快不破。同样的,kafka在消息队列领域,也是非常快的,这里的块指的是kafka在单位时间搬运的数据量大小,也就是吞吐量,下图是搬运网上的一个性能测试结果,在同步发送场景下,单机Kafka的吞吐量高达17.3w/s,不愧是高吞吐量消息中间件的行业老大。 那究竟

    2024年02月07日
    浏览(37)
  • 有了Spring为什么还需要SpringBoot呢

    目录 一、Spring缺点分析 二、什么是Spring Boot 三、Spring Boot的核心功能 3.1 起步依赖 3.2 自动装配 1. 配置文件和依赖太多了!!! spring是一个非常优秀的轻量级框架,以IOC(控制反转)和AOP(面向切面)为思想内核,极大简化了JAVA企业级项目的开发。虽然Spring的组件代码是轻

    2024年02月08日
    浏览(41)
  • 僵尸进程?孤儿进程?为什么他有如此惨烈的身世...

    🌸作者简介: 花想云 ,在读本科生一枚,C/C++领域新星创作者,新星计划导师,阿里云专家博主,CSDN内容合伙人…致力于 C/C++、Linux 学习。 🌸 专栏简介:本文收录于 Linux从入门到精通 ,本专栏主要内容为本专栏主要内容为Linux的系统性学习,专为小白打造的文章专栏。

    2024年02月05日
    浏览(50)
  • 为什么如此安全的https协议却仍然可以被抓包呢?(1)

    好了,阅读到了这里,说明你对https已经非常熟悉了,那么你一定知道,https协议是结合了非对称加密和对称加密一起工作,从而保证数据传输的安全性的。 非对称加密用于确保客户端可以安全地获取到服务器的真实公钥。对称加密用于确保客户端和服务器之间的数据传输不

    2024年04月26日
    浏览(35)
  • 『Linux从入门到精通』第 ⑭ 期 - 僵尸进程?孤儿进程?为什么他有如此惨烈的身世...

    🌸作者简介: 花想云 ,在读本科生一枚,C/C++领域新星创作者,新星计划导师,阿里云专家博主,CSDN内容合伙人…致力于 C/C++、Linux 学习。 🌸 专栏简介:本文收录于 Linux从入门到精通 ,本专栏主要内容为本专栏主要内容为Linux的系统性学习,专为小白打造的文章专栏。

    2024年02月16日
    浏览(59)
  • A Beginner‘s Guide to Apache Kafka: 什么是Kafka、它为什么如此受欢迎、它在哪些场景下可以应用、以及一些基本概念和术语

    作者:禅与计算机程序设计艺术 Apache Kafka(以下简称Kafka)是一个开源分布式流处理平台,它被设计用来实时传输大量的数据,从而能够实时的对数据进行处理并提取价值。本文通过梳理,引导读者了解什么是Kafka、它为什么如此受欢迎、它在哪些场景下可以应用、以

    2024年02月09日
    浏览(54)
  • 什么是 Spring?为什么学它?

    欢迎来到本篇文章!在这里,我将带领大家快速学习 Spring 的基本概念,并解答两个关键问题:什么是 Spring,以及为什么学习 Spring。 废话少说,下面,我们开始吧! Spring 官方文档:https://docs.spring.io/spring-framework/docs/5.2.24.RELEASE/spring-framework-reference/ 简化我们的企业级应用程

    2024年02月06日
    浏览(38)
  • stm32下载代码到单片机上需要调节BOOT为什么模式

    一、BOOT模式选择图解   二、BOOT模式介绍 所谓启动,一般来说就是指下好程序后,重启芯片时,SYSCLK的第4个上升沿,BOOT引脚的值将被锁存。用户可以通过设置BOOT1和BOOT0引脚的状态,来选择在复位后的启动模式。 A.   Main Flash memory 是STM32内置的Flash,一般我们使用JTAG或者S

    2023年04月15日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包