第一次学习用springboot3+ maven

11 阅读5分钟

一、首先,我的详细学习方式:

1.编程体会spring boot3+Maven

用(1)纯 Java 传统面向对象编程(手动创建对象)和(2)基于SpringBoot3+Maven 的方式(依赖注入管理对象)分别写应用场景:汽车厂生产了一辆车,我们家购买了1辆该车,2026年春节期间,我们家4人:爸爸、妈妈、我、外婆,驾驶这辆车去广东旅游。

(2)相比于(1)的核心区别:SpringBoot 3 + Maven 实现,通过依赖注入(DI)管理对象,替代手动 new 对象的方式,符合 Spring 生态的开发规范。

2.编写步骤

step1:Maven 依赖(pom.xml)(将各种依赖包复制粘贴进来)

step2:核心代码(按包结构组织)

在Java下面创建软件包,在软件包里建各种类(注意层次规范,有实体类、配置类、业务类、启动类等等)

二、途中的疑惑(springboot bean注入的逻辑和先后规则是什么样的)

(前提:将家庭成员外婆waiPo Bean前面的@Bean删掉会出现什么问题,进而引发的思考)

1.SpringBoot 依赖注入的核心逻辑

依赖注入的本质是:Spring 容器接管对象(Bean)的创建和管理,当某个 Bean 需要其他 Bean 时,容器自动把依赖的 Bean 「送」过去,无需手动 new 对象。

核心目标:解耦(对象不再自己创建依赖,而是由容器提供)。

案例理解:

我需要 Car Bean,而 Car 需要 Person Bean;

我只需要告诉 Spring「我要什么」,Spring 负责「找/创建」并「注入」。

2.SpringBoot 注入的完整执行顺序(容器启动流程)

步骤1:扫描并识别 Bean 定义(找「候选对象」)

  • SpringBoot 启动后,会扫描指定包下的类(默认是启动类所在包),识别所有「能创建 Bean」的标识:

  • 注解类:

@Component/@Service/@Controller/@Repository(业务类);

  • 配置类:

@Configuration + @Bean(手动声明 Bean);

  • 其他:

@RestController(组合注解)、@Entity(JPA,非核心)等。

  • 比如代码中的TripConfig 被 @Configuration 标记,里面的 @Bean 方法会被记录为「Bean 定义」。

步骤2:实例化 Bean(创建对象,无依赖)

  • Spring 先创建「无依赖的 Bean」:即不需要其他 Bean 就能创建的对象(比如

Person father(),无参数,直接 new)。

  • 顺序:先创建「基础 Bean」(比如工具类、实体类),再创建「依赖型 Bean」(比如Car,依赖 Person)。

步骤3:填充依赖(核心注入环节)

  • 对有依赖的 Bean(比如 Car 依赖 Person),Spring 会按「注入规则」找对应Bean,注入到当前 Bean 中:
  • 比如 crownRoader() 方法需要 4 个 Person 参数,Spring 会去容器中找匹配的 Person Bean 注入。
  • 若找不到匹配的 Bean → 抛 NoSuchBeanDefinitionException;
  • 若找到多个匹配的 Bean → 抛 NoUniqueBeanDefinitionException(我之前遇到了歧义错误,依赖Bean因为符合类型的无依赖Bean有多个找不到匹配的无依赖Bean的情况)。

步骤4:初始化 Bean(执行初始化逻辑)

  • 注入完成后,执行 Bean 的初始化方法(比如 @PostConstruct 注解的方法),最终将 Bean 放入「Spring 容器」(单例池)。

步骤5:Bean 就绪(供应用使用)

  • 所有 Bean 初始化完成后,SpringBoot 应用启动完成,可以通过 @Autowired/

Bean 方法参数 等方式获取容器中的 Bean。

3.注入的核心优先级规则(关键!)

当 Spring 需要为某个依赖找匹配的 Bean 时,会按以下优先级依次匹配,前面的规则优先于后面:

规则1:按「Bean 类型 + 限定符(@Qualifier)」匹配(最高优先级)

  • 若用 @Qualifier("bean名称") 明确指定 Bean 名称,Spring 会直接按「类型 + 名称」找,忽略其他规则:
// 直接找名称为father的Person Bean,不管容器中有多少个Person类型
@Bean
public Car crownRoader(@Qualifier("father") Person p1) { ... }
//crownRoader是车型,即Car类的一个实例
  • 这是解决「多同类型 Bean 歧义」的核心方式。

规则2:按「Bean 类型 + 参数名/字段名」匹配(默认规则)

若没有 @Qualifier,Spring 会先按「类型」筛选:

若类型匹配的 Bean 只有 1 个 → 直接注入(不管名称是否一致);

若类型匹配的 Bean 有多个 → 再按「参数名/字段名」匹配 Bean 名称(Bean 名称默认是方法名/类名首字母小写)。

比如代码中:

容器中有 3 个 Person 类型 Bean(father、mother、me);

crownRoader() 参数是 Person father → Spring 先看类型(Person),发现有 3 个,直接报歧义错误(不会再看参数名)。

规则3:按「@Primary」注解匹配(次优先级)

若多个同类型 Bean 中,有一个被@Primary 标记,Spring 会优先注入这个 Bean:

@Bean
@Primary // 优先注入这个Bean
public Person father() { return new Person("爸爸"); }

@Bean
public Person mother() { return new Person("妈妈"); }

// 此时注入Person会优先用father,不会报歧义
@Bean
public Car crownRoader(Person p) { ... }

规则4:按「Bean 的作用域」匹配(兜底)

若前面规则都匹配不到,Spring 会按作用域筛选(默认是单例 singleton):

singleton:全局唯一 Bean(默认);

prototype:每次注入都创建新 Bean;(极少用)

request/session:Web 环境专用。

4.结合代码案例,再理解规则

将之前思考的代码问题,用规则拆解:

waiPo() 无 @Bean → 步骤1 未被识别为 Bean 定义 → 步骤2 未创建 → 步骤3 找不到waiPo Bean;

容器中有 3 个 Person 类型 Bean → 步骤3 按规则2 匹配时,类型匹配数>1 → 直接报歧义错误(不会走到「参数名匹配」);

修复方案:给 waiPo() 加

@Bean → 步骤2 创建 waiPo Bean;

给参数加

@Qualifier → 按规则1 精准匹配,跳过类型歧义检查。

总结

核心逻辑:Spring 容器先创建所有 Bean 定义 → 实例化无依赖 Bean → 按规则注入依赖 → 初始化 Bean;

先后顺序:

扫描 Bean 定义 → 实例化无依赖 Bean → 注入依赖 → 初始化 → 就绪;

优先级规则:

@Qualifier(精准名称) > @Primary(优先 Bean) > 类型+参数名(默认) > 作用域;

避坑关键:多同类型 Bean 必须用 @Qualifier 或 @Primary 明确指定,否则必报歧义错误。