当前位置: 首页 > news >正文

Spring IoC 超清晰讲解:Bean、容器、依赖注入全流程

目录

  • Spring IOC
    • 一、什么是 IoC?
    • 二、IoC 的核心:IoC 容器
    • 三、IoC 和 Bean 的关系
    • 四、IoC 的依赖注入(DI)
      • 常见方式:
      • 依赖注入的原理(源码角度)
        • 依赖查找的顺序:
      • 依赖注入的细节
    • 五、IoC 的好处
    • 六、Spring IOC 的加载过程
      • 1. 资源定位(Resource 定位配置文件/注解)
      • 2. 解析配置,生成 **BeanDefinition**
      • 3. BeanFactoryPostProcessor 阶段(修改 BeanDefinition)


Spring IOC

一、什么是 IoC?

  • 直白点:原来对象的创建、依赖关系要我们自己 new、自己管理;现在交给 Spring 容器来做。
  • 控制反转:控制权从“开发者”反转到“容器”。

例如没有 Spring 时:

UserService userService = new UserService(new UserRepository());

我们需要手动 new,自己决定依赖怎么创建。

有了 Spring 后:

UserService userService = context.getBean(UserService.class);

Spring 容器帮我们:

  1. 创建对象(Bean)
  2. 解决依赖关系(注入)
  3. 管理生命周期

二、IoC 的核心:IoC 容器

IoC 容器就是一个“大工厂”,里面存放着各种 Bean,**负责整个 Bean 的生命周期管理。**常见实现:

  • BeanFactory:IoC 的最基本容器,按需加载(懒加载)。
  • ApplicationContext:BeanFactory 的子接口,功能更强大,支持事件发布、国际化、AOP 等,几乎开发中都是用它。

三、IoC 和 Bean 的关系

  • Bean:容器管理的对象(Java 类实例)。
  • BeanDefinition:Bean 的“元数据”(配方/蓝图),描述如何创建这个 Bean。
    • 类的全限定名
    • 作用域(singleton、prototype…)
    • 初始化方法、销毁方法
    • 依赖关系

容器根据 BeanDefinition 来生产 Bean,就像工厂根据图纸来生产零件。


四、IoC 的依赖注入(DI)

Dependency Injection:对象的依赖不是自己去 new,而是由 Spring 注入。

依赖:一个类需要另外一个类来完成工作,比如:

class UserService {private UserRepository userRepository; // 依赖
}

UserService 想操作用户,就必须依赖 UserRepository

注入:这个依赖不是 UserService 自己去 new,而是 Spring 帮你塞进去

@Service
class UserService {@Autowiredprivate UserRepository userRepository; // Spring注入
}

通俗理解:

  • 控制反转(IoC) = 你不用自己创建对象,Spring 来管。
  • 依赖注入(DI) = Spring 把你需要的依赖塞给你。

常见方式:

  1. 构造器注入(推荐)

    //构造器注入(Spring Boot 下可以省略 @Autowired)
    @Component
    public class UserService {private final UserRepository userRepository;@Autowiredpublic UserService(UserRepository userRepository) {this.userRepository = userRepository;}
    }
    
  2. Setter 注入

    @Component
    public class UserService {private UserRepository userRepository;@Autowiredpublic void setUserRepository(UserRepository userRepository) {this.userRepository = userRepository;}
    }
    
  3. 字段注入

    @Component
    public class UserService {@Autowiredprivate UserRepository userRepository;
    }
    

依赖注入的原理(源码角度)

  1. 扫描 & 解析 BeanDefinition
    • @ComponentScan 会找到 @Component@Service@Repository@Controller 标注的类。
    • 这些类会被解析成 BeanDefinition(保存类信息、依赖信息、作用域等)。
  2. 创建 Bean
    • Spring IOC 容器根据 BeanDefinition 通过反射创建对象。
  3. 依赖注入(DI)
    • Spring 调用 AutowiredAnnotationBeanPostProcessor,解析 @Autowired
    • 找到匹配的 Bean(按类型 → 按名称 → @Qualifier → @Primary)。
    • 通过反射赋值(字段/构造器/Setter)。

依赖查找的顺序:

1. 按类型找(byType)

  • 比如你写了:

    @Autowired
    private UserRepository userRepository;
    

    Spring 会去 IOC 容器里找 UserRepository 类型的 Bean

  • 如果只有一个,就直接注入。

2. 多个 Bean 时 → 按名称(byName)

  • 如果 IOC 里有两个 UserRepository 实现,比如:

    @Repository("userRepo1")
    class UserRepositoryImpl1 implements UserRepository {}@Repository("userRepo2")
    class UserRepositoryImpl2 implements UserRepository {}
    

    那么 Spring 就会看看 变量名 userRepository,有没有和某个 Bean 的名字匹配。

    • 如果匹配成功 → 注入对应的 Bean。
    • 如果不匹配 → 报错(NoUniqueBeanDefinitionException)。

3. @Qualifier 指定

  • 如果你明确指定了:

    @Autowired
    @Qualifier("userRepo1")
    private UserRepository userRepository;
    

    Spring 就会按照 userRepo1 这个名字去注入。


4. @Primary 标记默认

  • 你也可以在某个 Bean 上标记:

    @Repository
    @Primary
    class UserRepositoryImpl1 implements UserRepository {}
    

    那么即使有多个同类型的 Bean,Spring 也会默认选这个。


依赖注入的细节

  1. 按类型注入(默认)
    • 如果 IOC 容器中有一个对应类型的 Bean,就直接注入。
    • 如果有多个,会报错 → 除非:
      • @Primary:指定默认首选
      • @Qualifier("beanName"):指定注入哪个
  2. 循环依赖问题
    • Spring 通过 三级缓存(singletonObjects、earlySingletonObjects、singletonFactories)解决了大多数循环依赖。
    • 但是 构造器注入无法解决循环依赖。

五、IoC 的好处

  • 解耦:对象只关心“需要什么”,不关心“如何得到”。
  • 统一管理:Spring 负责对象的创建、初始化、销毁。
  • 可扩展:通过配置或注解就能替换实现,而不用改代码。
  • 便于测试:可以轻松替换依赖。

总结一句话:
Spring IoC 是一种设计思想,用容器来管理对象和它们的依赖关系,开发者只需要声明需求,容器负责提供和维护。


六、Spring IOC 的加载过程

1. 资源定位(Resource 定位配置文件/注解)

  • 容器启动时,先要知道 Bean 的配置来源:
    • XML<bean> 标签
    • 注解@ComponentScan@Bean
    • Java 配置类@Configuration
  • Spring 通过 ResourceLoader 找到这些配置文件/类。

2. 解析配置,生成 BeanDefinition

  • Spring 使用 BeanDefinitionReader 来解析配置。
  • 每一个 <bean>@Component → 转换成一个 BeanDefinition 对象
  • BeanDefinition 就是 Bean 的“元信息”(类似于建模),里面存放:
    • Bean 的 class 类型
    • 作用域(scope)
    • 是否懒加载(lazy-init)
    • 属性值、依赖信息
  • Spring 把这些 BeanDefinition 存到一个 BeanDefinitionMap(ConcurrentHashMap) 里。
    • Key = Bean 名称
    • Value = BeanDefinition

3. BeanFactoryPostProcessor 阶段(修改 BeanDefinition)

BeanDefinition 和 完整BeanDefinition 中间通过一个后置增强器,可以对bean的定义信息进行统一修改,只需要实现 BeanFactoryPostProcessor 接口即可,这个后置增强器是可以有多个的,你只要在不同的类实现多个 BeanFactoryPostProcessor 接口就会执行多次

  • 比如:@ConfigurationProperties 就是通过这个阶段注入属性值的。
http://www.dtcms.com/a/442841.html

相关文章:

  • 政务公开网站建设方案小说网站建设详细流程
  • Next.js create-next-app命令介绍
  • 如何做一个自己的网站公司建设网站需求分析报告
  • 《API网关在智能制造MES联动中的实战应用》
  • 番禺网站建设知乎qq中心官方网站
  • 阿里云 网站部署网站更换程序
  • JavaScript 输出
  • AngularJS Bootstrap:深入浅出指南
  • vs2015做的网站广东广州重大新闻
  • 机器学习决策树与大模型的思维树
  • 宁波建站wordpress网站安装插件
  • 无锡网站建设团队南通 外贸建站
  • 河源市网站建设东莞交易中心
  • [Linux基础——Lesson10.Linux环境下普通用户 sudo 提权]
  • 兰州网站建设兼职山东兴润建设集团网站
  • 内存总线(Memory Bus)是什么?
  • 深圳建筑业网站建设现在市场最火的网店平台
  • DrvBsp_I2C驱动_EEPROM(一)
  • JAVA实现评委打分
  • 建设网站需要哪些职位营销策略有哪些有效手段
  • 工艺品网站建设开发青羊区建设局网站
  • ViT实战一:Patch_embedding
  • Java8+新特性
  • 网站的根目录怎么找境外网站不备案盈利
  • 【Linux】Linux 常用指令2
  • 买服务器做网站百度云搜索引擎入口手机版
  • 算法入门:专题攻克主题一---双指针(2)快乐数 呈最多水的容器
  • 中国建设银行移动门户网站广州市花
  • 手写MyBatis第92弹:SqlSource体系、SqlNode树与Trim标签实现原理全揭秘
  • Perl 简介