【SpringBoot】——原理篇

发布于:2025-09-13 ⋅ 阅读:(21) ⋅ 点赞:(0)

目录

一.bean的加载方式(8种)

1.

2.

3.@import(普通类,配置类)

4.ImportSelector(可以做判定)

5.ImportBeanDefineRegistrar(6的升级版)

二.自动装配

流程

总结

三.自定义starter

四.启动流程

五.Maven

1.maven有什么用

2.基础概念

1.仓库

2.坐标

3.依赖管理

1.依赖传递

4.多模块开发

1.聚合

2.继承

3.属性(版本统一的重要性)变量名

4.版本管理

5.资源配置

6.多环境开发配置(生产,开发,测试环境不同)

7.私服

1.仓库的类别

2.本地仓库访问私服

3.上传项目到私服中

六.springboot比spring好在哪?它为啥方便了?

1.parent(仅仅是定义了还没使用哦)

2.starter(starter里面有若干东西)

3.引导类(靠谁运行)


一.bean的加载方式(8种)

1.

2.

3.@import(普通类,配置类)

好处:被导入的类不用声明成bean

4.ImportSelector(可以做判定)

 为什么要这么折腾一圈呢?

元数据,导入的类的元数据。哪里用了@import注解谁就是这个元数据

这种方式加载bean,不仅可以加载bean,还可以做判定。这个东西selector选择器,可以进行一系列的判定,判定完成后,再决定是否加载指定的bean。@import在哪个配置文件上,检测的就是谁。

5.ImportBeanDefineRegistrar(6的升级版)

上一个只能加载bean,这一个可以修改bean了,也可以说是管理bean。

二.自动装配

ImportSelector 可以进行各种条件的判定,判定完毕后,决定是否加载指定的bean

                                      有什么条件呢?

可以得出,它不仅能加载bean。还可以控制加载谁,可以根据条件动态的加载bean,哪个配置类导入了它(@import),它就检测哪个配置类。

ImportBeanDefinitionRegistrar

这个对比上一个方法,你可以管理bean了,上一个方法你只能输个全限定名就给你加载了,但这个方法你可以动bean了。因为你拿到了Beandefinition。

举一个例子:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(MyBeanRegistrar.class)  // 👈 关键!
public @interface EnableMyService {
}



@Override
public void registerBeanDefinitions(
        AnnotationMetadata importingClassMetadata,
        BeanDefinitionRegistry registry) {

    // 1. 构建一个 BeanDefinition(通过 BeanDefinitionBuilder)
    BeanDefinitionBuilder builder = BeanDefinitionBuilder
            .rootBeanDefinition(MyService.class); // 指定要注册的类是 MyService

    // 2. 手动调用 registry.registerBeanDefinition(...) 注册它
    registry.registerBeanDefinition("myService", builder.getBeanDefinition());

    // 👆 就是这行代码!!!体现了“手动注册 BeanDefinition”
}


@Configuration
@EnableMyService  // 👈 一加这个注解,就会触发导入 MyBeanRegistrar
public class AppConfig {
}

Spring 在启动时,会:

  • 解析到 @EnableMyService
  • 看到它使用了 @Import(MyBeanRegistrar.class)
  • ​​就会把 MyBeanRegistrar 这个类加载进来,并调用它的 registerBeanDefinitions() 方法​​
  • 在这个方法中,你调用了 registry.registerBeanDefinition(...),也就是 ​​手动告诉 Spring:请把某个类(比如 MyService)注册为一个 Bean,它的定义是啥啥啥​​
  • ​​Spring 拿到这个 BeanDefinition 后,就会根据它去实例化和管理真正的 Bean 对象​

@Import(ImportBeanDefinitionRegistrar.class) 的作用就是:在 Spring 启动时,把一个实现了 ImportBeanDefinitionRegistrar 接口的类加载进来,然后调用它的 registerBeanDefinitions 方法,让你有机会通过编程的方式,手动向 Spring 容器注册 BeanDefinition,从而控制 Bean 的加载。​

​你注册了 BeanDefinition,Spring 就知道:“哦!我要创建这个 Bean!”,然后它就会去实例化和管理它。​

Spring 容器本质是一个 ​​Bean 工厂​​,它管理的不是对象,而是 ​​Bean 的定义(BeanDefinition)​。 ​​BeanDefinition 是 Spring 中描述一个 Bean 的配置信息(比如类名、作用域、构造方法等)的对象,它相当于 Bean 的“配方”或“元数据”。​

​Spring 不直接操作你的类,而是先根据 BeanDefinition 去实例化和管理 Bean。​

​所以,你只要手动注册一个 BeanDefinition(告诉 Spring 这个类要被管理),Spring 就会按照这个定义去创建和管理 Bean,从而实现你想要的 Bean 注册和控制。​

BeanDefinitionRegistryPostProcessor

====================================================

@EnableAutoConfiguration

1.扫描包及其子包

2.读取自动配置类

3.注册符合条件的配置类

  • @Import(AutoConfigurationPackages.Registrar.class)

 得到了一个com.itheima。需要扫描下面的东西,扫哪里就通过这个,扫描的包路径。说白了就是springboot怎么知道要扫描哪些包,就是设置当前所在的包作为扫描包,后续针对当前的包进行扫描。

  • @Import(AutoConfigurationImportSelector.class)

分为三大类:

1.Aware:想用哪些,实现这些aware接口就可以了

2.ordered:加载顺序,有时候加载一个bean需要依赖某一个bean,这个bean加载了我才加载。

3.Deferred :推迟加载

获取META-INF/spring.factories。这个东西是啥?初始默认加载的一大堆东西。

流程

1.springboot启动,@SpringBootApplication里面有一个@EnableAutoConfiguration

2.@EnableAutoConfiguration 的作用是​​告诉 Spring Boot:“请开始自动装配!”​
它的底层通过 @Import(AutoConfigurationImportSelector.class) 实现,关键类是:

  • AutoConfigurationImportSelector​:负责从类路径中​​筛选并加载自动配置类​​。(按条件加载)

3.AutoConfigurationImportSelector 的工作流程如下:

读取所有候选的自动配置类​

  • 从 ​​所有依赖的 JAR 包​​ 中查找 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件(Spring Boot 2.7+ 版本)。

其中某一个自动配置类被列在文件中,并不是无条件加载,而是需要通过@conditional系列注解的判断。

  • @ConditionalOnClass(DataSource.class):类路径下必须有 DataSource 类(比如引入了 spring-jdbc 依赖)。
  • @ConditionalOnProperty(name = "spring.datasource.url"):配置文件中必须配置了数据库 URL。
  • @ConditionalOnMissingBean(DataSource.class):容器中不能已经存在 DataSource 的 Bean(避免重复注册)。

注册符合条件的自动配置类​

  • 通过 BeanDefinitionRegistry 将筛选后的自动配置类注册到 Spring 容器中。
    • BeanDefinitionRegistry .registryBeanDefinition("beanName",bean.class)
  • 这些自动配置类内部通常会定义一些 Bean(如 DataSourceDispatcherServlet),从而完成自动装配。

总结

初始化环境:自定义的bean 如@bean注解 以及导入的坐标 maven,形成初始化的环境

设置集A:扫描出的META-INF中全部文件,但不是真的加载,还需要看条件满不满足。与初始化的环境进行比对,满足就加载,不满足就不加载。

设置集B:加载满足加载条件技术的配置文件,有带默认值的,也有不带的,完全取决于给你配置成什么样。默认加载,如果想覆盖,你就修改即可。

三.自定义starter

四.启动流程

五.Maven

1.maven有什么用

2.基础概念

1.仓库

2.坐标

3.依赖管理

1.依赖传递

可选依赖:optional:不被别人知道我有这个

排除依赖:exclude:主动不要别人这个

依赖范围:scope:

4.多模块开发

1.聚合

如果一个模块更新了,出现问题了。

2.继承

不兼容了,出现问题。怎么解决?用一个父类统一写上(也就是依赖管理),后面的去继承它就好了,后续的工程就不需要再写版本了,以此达到避免依赖冲突的问题。

3.属性(版本统一的重要性)变量名

后面依赖中的version就可以写成${...}了

4.版本管理

5.资源配置

6.多环境开发配置(生产,开发,测试环境不同)

7.私服

1.仓库的类别

创建仓库,并放到仓库组中。比如release,snapshots等

2.本地仓库访问私服

配置本地仓库的setting,第一个用户名和密码,让本地仓库有权限访问我们的私服

第二个是下载的地址,一个仓库从中央仓库中拿(阿里云),其余的全从仓库组来

3.上传项目到私服中

package:只是做一个打包,生成在开发路径下的

install:上传到本地仓库

deploy: 上传到私服中(发到哪就看你上面配置的是哪)

六.springboot比spring好在哪?它为啥方便了?

简化spring应用的初始搭建以及开发过程。

1.parent(仅仅是定义了还没使用哦)

几个工程project都依赖了相同的东西,写的话就重复了。

拿一个project-dependency一个pom统一管理,同时将版本拆出去变成maven的属性,dependency中直接引用就可以了。

那具体是怎么做的呢?

又继承这个dependency

这个dependency定义了一系列的坐标属性properties

而且定义了一个依赖管理dependencyManagement,引用了上面的版本。

所以我们在引入时就不用写坐标了,不用管坐标了。避免了依赖冲突现象的发生。

2.starter(starter里面有若干东西)

一个starter包含了若干个依赖的信息。实现了快速的配置,减少依赖配置的目的

3.引导类(靠谁运行)


网站公告

今日签到

点亮在社区的每一天
去签到