Spring Boot项目中Spring容器原理解析

 更新时间:2025年12月18日 10:59:40   作者:漂亮的小碎步丶  
这篇文章详细介绍了Spring BootCrudDemo项目中Spring核心容器的工作原理,包括容器启动过程、依赖注入机制以及核心组件的应用,感兴趣的朋友跟随小编一起看看吧

拆解一个具体的spring-boot-crud-demo项目作为示例,尝试找出Spring核心容器原理在实际项目中的应用。

1. 项目结构

src/main/java/com/example/demo/
├── SpringBootCrudDemoApplication.java  # 主启动类
├── User.java                           # 实体类
├── UserController.java                 # 控制器
└── UserRepository.java                 # 数据访问接口

2. ApplicationContext容器启动过程

2.1 启动入口:主启动类

package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootCrudDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootCrudDemoApplication.class, args);
    }
}

2.2 启动过程详解

2.2.1 阶段一:容器初始化

当我们运行SpringApplication.run()方法时:

  1. 创建AnnotationConfigServletWebServerApplicationContext实例(Web环境下的ApplicationContext实现)
  2. 加载@SpringBootApplication注解中的配置信息
  3. 初始化DefaultListableBeanFactory作为底层Bean工厂
  4. 注册Spring Boot内置的BeanPostProcessor,如自动代理创建器、配置属性绑定处理器等

2.2.2 阶段二:Bean定义加载

  • 组件扫描@SpringBootApplication包含@ComponentScan,会扫描当前包及其子包
    • 扫描到UserController@RestController@Component的特化)
    • 不会扫描到UserRepository,因为它是接口
  • 自动配置@SpringBootApplication包含@EnableAutoConfiguration,会加载:
    • Spring Data JPA自动配置(HibernateJpaAutoConfiguration
    • Spring Web MVC自动配置(WebMvcAutoConfiguration
    • 嵌入式Web服务器自动配置(TomcatServletWebServerFactoryAutoConfiguration)等
  • BeanDefinition注册
    • 注册UserController的BeanDefinition
    • 自动配置类注册大量内置BeanDefinition,如DispatcherServletDataSourceEntityManagerFactory
    • UserRepository通过@EnableJpaRepositories(由@SpringBootApplication间接导入)被动态代理并注册

2.2.3 阶段三:Bean实例化与初始化

  • 实例化Bean
    • 调用UserController的无参构造方法创建实例
    • 创建DataSourceEntityManagerFactory等基础组件实例
    • UserRepository创建动态代理实例
  • 依赖注入
  • @Autowired
    private UserRepository userRepository;
    
    • 容器将UserRepository的代理实例注入到UserControlleruserRepository字段中
  • 初始化
    • 调用UserController的初始化方法(如果有)
    • 应用BeanPostProcessor的处理,如AOP代理、事务增强等

2.2.4 阶段四:容器启动完成

  1. 发布ContextRefreshedEvent事件
  2. 启动嵌入式Tomcat服务器
  3. 注册请求映射(如UserController中的@RequestMapping
  4. 应用准备就绪,开始处理HTTP请求

3. 依赖注入原理

3.1 字段注入示例

UserController中,我们使用了字段注入:

@RestController
@RequestMapping("/api/users")
public class UserController {
    @Autowired
    private UserRepository userRepository;
    // ...
}

3.2 依赖注入过程详解

  • 依赖解析
    • 容器在实例化UserController后,发现userRepository字段上有@Autowired注解
    • 确定依赖类型为UserRepository
  • 依赖查找
    • 容器在Bean工厂中查找UserRepository类型的Bean
    • 由于UserRepository是接口,容器会查找其实现类或代理类
    • 找到由Spring Data JPA创建的动态代理实例
  • 依赖注入
    • 使用反射技术,将UserRepository的代理实例赋值给UserControlleruserRepository字段
    • 完成注入后,UserController就可以使用userRepository来操作数据了

3.3 依赖注入的优势

在这个项目中,我们可以看到依赖注入的实际优势:

  1. 松耦合UserController不需要关心UserRepository的具体实现
  2. 可测试性:在单元测试中,可以轻松替换UserRepository为模拟实现
  3. 代码简洁:不需要手动创建UserRepository实例

4. 核心组件在项目中的具体体现

4.1 BeanFactory

  • 实现类DefaultListableBeanFactory
  • 作用:管理项目中所有的Bean,包括UserControllerUserRepository代理、DataSource
  • 位置:作为AnnotationConfigServletWebServerApplicationContext的底层实现

4.2 ApplicationContext

  • 实现类AnnotationConfigServletWebServerApplicationContext
  • 作用:提供完整的容器功能,包括Web应用支持、事件发布、资源访问等
  • 位置:通过SpringApplication.run()方法创建并返回

4.3 BeanDefinition

  • UserController的BeanDefinition:
    • 类名:com.example.demo.UserController
    • 作用域:默认单例
    • 注解:@RestController@RequestMapping
    • 依赖:UserRepository
  • UserRepository的BeanDefinition:
    • 类名:com.example.demo.UserRepository
    • 类型:接口
    • 实现:由Spring Data JPA动态生成

4.4 BeanPostProcessor

  • AutowiredAnnotationBeanPostProcessor:处理@Autowired注解,实现依赖注入
  • JpaRepositoryFactoryBean:创建UserRepository的代理实例
  • TransactionAnnotationBeanPostProcessor:处理@Transactional注解,实现事务管理

5. 实际运行流程

当我们访问http://localhost:8080/api/users时:

  1. 浏览器发送HTTP GET请求到Tomcat服务器
  2. Tomcat将请求转发给Spring MVC的DispatcherServlet
  3. DispatcherServlet查找匹配的处理器,找到UserControllergetAllUsers()方法
  4. DispatcherServlet调用UserController实例的getAllUsers()方法
  5. 在方法内部,UserController使用注入的userRepository调用findAll()方法
  6. userRepository的代理实例将请求转发给底层的JPA实现
  7. JPA执行SQL查询,从H2数据库获取所有用户数据
  8. 结果逐层返回,最终响应给浏览器

6. 总结

通过spring-boot-crud-demo项目,可以清晰地看到Spring核心容器在实际项目中的应用:

  • ApplicationContext启动:从@SpringBootApplication注解开始,经历容器初始化、Bean定义加载、Bean实例化与初始化、容器启动完成四个阶段
  • 依赖注入:通过@Autowired实现Bean之间的依赖注入,如UserController依赖UserRepository
  • 核心组件:BeanFactory管理Bean,ApplicationContext提供完整容器功能,BeanDefinition定义Bean元数据,BeanPostProcessor增强Bean功能

到此这篇关于Spring Boot项目中Spring核心容器原理详解的文章就介绍到这了,更多相关springboot项目spring容器原理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用idea启动DataX的方法示例

    使用idea启动DataX的方法示例

    这篇文章主要介绍了使用idea启动DataX的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-01-01
  • Java中遍历JSON文件的详细步骤

    Java中遍历JSON文件的详细步骤

    JSON作为一种轻量级数据交换格式,在IT领域被广泛应用,文章将指导如何在Java中使用Jackson库遍历JSON文件内容,本文给大家介绍了Java中遍历JSON文件的详细步骤,需要的朋友可以参考下
    2025-08-08
  • Java虚拟机装载和初始化一个class类代码解析

    Java虚拟机装载和初始化一个class类代码解析

    这篇文章的主要内容是Java虚拟机装载和初始化一个class类的代码解析,包括介绍了装载和初始化的时机与方式,需要的朋友可以参考下。
    2017-09-09
  • Java中的运算符你知道多少

    Java中的运算符你知道多少

    这篇文章主要为大家详细介绍了Java中的运算符,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • 详解非spring框架下使用querydsl的方法

    详解非spring框架下使用querydsl的方法

    Querydsl是一个采用API代替拼凑字符串来构造查询语句,可跟 Hibernate 和 JPA 等框架结合使用。本文介绍的是非spring环境下querydsl JPA整合使用,感兴趣的小伙伴们可以参考一下
    2019-01-01
  • Spring MVC 中 短信验证码功能的实现方法

    Spring MVC 中 短信验证码功能的实现方法

    短信验证功能在各个网站应用都非常广泛,那么在springmvc中如何实现短信验证码功能呢?今天小编抽时间给大家介绍下Spring MVC 中 短信验证码功能的实现方法,一起看看吧
    2016-09-09
  • 使用Java通过OAuth协议验证发送微博的教程

    使用Java通过OAuth协议验证发送微博的教程

    这篇文章主要介绍了使用Java通过OAuth协议验证发送微博的教程,使用到了新浪微博为Java开放的API weibo4j,需要的朋友可以参考下
    2016-02-02
  • Redis缓存实例分步详解

    Redis缓存实例分步详解

    实际开发中缓存处理是必须的,不可能我们每次客户端去请求一次服务器,服务器每次都要去数据库中进行查找,为什么要使用缓存?说到底是为了提高系统的运行速度
    2023-04-04
  • Java操作MongoDB模糊查询和分页查询

    Java操作MongoDB模糊查询和分页查询

    这篇文章主要介绍了Java操作MongoDB模糊查询和分页查询的相关资料,需要的朋友可以参考下
    2016-04-04
  • springboot集成easypoi导出word换行处理过程

    springboot集成easypoi导出word换行处理过程

    Spring Boot集成Easypoi导出Word时,换行符\n失效显示为空格,解决方法包括生成段落或替换模板中\n为回车,同时需确保变量{{temp}}在Map中设为"  "(带空格空字符串),避免空指针或残留变量
    2025-08-08

最新评论