【Spring】Spring Core解析

深入了解Spring Core的核心原理、核心组件、实际使用方式以及底层逻辑,搞清楚它作为整个Spring生态基石的具体实现和价值。

Spring Core是Spring框架的根模块 ,也是所有Spring扩展框架(如Spring Boot、Spring MVC)的底层基础。它的核心使命是通过控制反转(IoC)依赖注入(DI) 实现对象的解耦管理,彻底改变传统Java开发中对象创建和依赖管理的方式。下面我会从「核心思想」→「核心组件」→「实际使用」→「底层流程」逐层拆解,结合代码示例让你彻底理解。


一、Spring Core的核心思想:IoC & DI

这是Spring Core的灵魂,先把这两个概念讲透,后续所有内容都围绕它们展开。

1. 控制反转(IoC,Inversion of Control)

概念解释

传统Java开发中,程序员掌控对象的生命周期

java 复制代码
// 传统方式:手动new对象,控制创建和依赖
public class UserService {
    // 手动创建依赖的UserDao对象
    private UserDao userDao = new UserDaoImpl();
    
    public void getUser() {
        userDao.queryUser();
    }
}

这种方式的问题:对象耦合度极高------如果UserDaoImpl的构造方式变了(比如需要传参数),所有new它的地方都要改;如果要替换UserDao的实现类(比如UserDaoMysqlImpl),也要逐个修改。

IoC的核心是反转控制权

  • 把对象的「创建、初始化、依赖注入、销毁」全部交给Spring IoC容器管理;
  • 程序员只需要「定义对象」和「声明依赖」,无需手动new对象。
通俗比喻

传统方式:你(程序员)亲自买菜、切菜、炒菜(手动创建所有对象);

IoC方式:你告诉餐厅(Spring容器)要吃什么菜(声明需要的对象),餐厅帮你准备好所有食材和餐具(创建对象+注入依赖),你只需要吃(使用对象)就行。

2. 依赖注入(DI,Dependency Injection)

概念解释

DI是IoC的具体实现方式:当Spring容器创建一个对象(比如UserService)时,会自动将它依赖的其他对象(比如UserDao)"注入"到这个对象中,无需程序员手动设置。

DI解决的核心问题:对象之间的依赖解耦------UserService不再关心UserDao是怎么创建的,只关心怎么使用它。


二、Spring Core的核心组件

Spring Core的核心是「IoC容器」,所有功能都围绕容器展开,核心组件如下:

1. Bean:Spring容器的管理单元

  • 定义:所有被Spring IoC容器管理的Java对象都叫Bean(本质就是普通的POJO,比如UserService、UserDao);
  • 区别 :普通Java对象是new出来的,Bean是由Spring容器创建、管理、销毁的;
  • 标识:通过注解(@Component/@Service/@Repository/@Controller)或XML配置告诉Spring"这个类要被当作Bean管理"。

2. BeanFactory:IoC容器的根接口

  • 定位 :定义了IoC容器的最基础规范(比如获取Bean、判断Bean是否存在、获取Bean类型等);
  • 核心方法getBean(String beanName)(根据名称获取Bean)、getBean(Class<T> requiredType)(根据类型获取Bean);
  • 特点
    • 轻量级,只实现了最核心的IoC功能;
    • 延迟初始化 :只有调用getBean()时才创建Bean实例(节省内存,但启动快);
    • 实际开发中几乎不直接使用(功能太简单)。

3. ApplicationContext:BeanFactory的增强版(实际开发首选)

  • 定位:BeanFactory的子接口,是Spring最常用的IoC容器;

  • 扩展功能 (相比BeanFactory):

    • 立即初始化:容器启动时就创建所有单例Bean(启动慢,但运行时响应快);
    • 支持国际化、资源加载(读取配置文件)、事件发布/监听;
    • 整合Spring AOP、事务管理等;
  • 常见实现类 (开发中常用):

    实现类 适用场景
    AnnotationConfigApplicationContext 基于注解配置类的容器(主流)
    ClassPathXmlApplicationContext 基于XML配置文件的容器(老旧项目)
    WebApplicationContext Web环境下的容器(如Spring MVC)

4. BeanDefinition:Bean的"定义说明书"

  • 定位:Spring容器内部用来描述Bean的元数据(相当于Bean的"身份证");
  • 包含信息:Bean的类型、作用域、依赖对象、初始化/销毁方法等;
  • 底层逻辑:Spring启动时,会先扫描所有Bean的定义(注解/XML),转换成BeanDefinition,再根据BeanDefinition创建Bean实例。

三、Spring Core的实际使用(代码示例)

下面通过完整的代码示例,演示Spring Core的核心用法(基于注解,主流方式)。

前置条件

  1. 新建Maven项目,引入Spring Core依赖(如果用Spring Boot,只需引入spring-boot-starter):
xml 复制代码
<!-- 纯Spring Core依赖 -->
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>6.1.2</version> <!-- 推荐使用稳定版 -->
    </dependency>
</dependencies>

步骤1:定义Bean(声明需要被容器管理的对象)

java 复制代码
// 1. 数据访问层Bean(@Repository是@Component的衍生注解,语义更明确)
@Repository
public class UserDao {
    public void queryUser() {
        System.out.println("查询用户信息");
    }
}

// 2. 业务层Bean(@Service同理)
@Service
public class UserService {
    // 声明依赖:需要UserDao对象
    private final UserDao userDao;

    // 推荐:构造器注入(Spring 4.3+支持自动注入,无需@Autowired)
    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }

    public void getUserInfo() {
        // 直接使用注入的UserDao,无需new
        userDao.queryUser();
    }
}

步骤2:配置IoC容器(告诉Spring扫描哪些包)

java 复制代码
// 配置类:@Configuration标识这是Spring的配置类
@Configuration
// 组件扫描:告诉Spring扫描com.example包下的所有注解(@Service/@Repository等)
@ComponentScan("com.example")
public class SpringConfig {
    // 无需额外代码,扫描后Spring会自动创建Bean
}

步骤3:启动容器并使用Bean

java 复制代码
public class SpringCoreDemo {
    public static void main(String[] args) {
        // 1. 创建ApplicationContext容器(基于注解配置)
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);

        // 2. 从容器中获取UserService Bean(两种方式)
        // 方式1:根据类型获取(推荐)
        UserService userService = context.getBean(UserService.class);
        // 方式2:根据名称获取(默认名称是类名首字母小写,如userService)
        // UserService userService = (UserService) context.getBean("userService");

        // 3. 使用Bean
        userService.getUserInfo(); // 输出:查询用户信息
    }
}

依赖注入的3种方式(补充)

上面用了构造器注入(推荐),另外两种方式如下:

java 复制代码
@Service
public class UserService {
    // 方式1:字段注入(简单但不推荐,不利于单元测试)
    // @Autowired
    // private UserDao userDao;

    // 方式2:Setter注入(适合可选依赖)
    // private UserDao userDao;
    // @Autowired
    // public void setUserDao(UserDao userDao) {
    //     this.userDao = userDao;
    // }

    // 方式3:构造器注入(推荐,强制依赖,确保对象创建时依赖已初始化)
    private final UserDao userDao;
    @Autowired // Spring 4.3+单构造器可省略
    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }
}

四、Spring Core的核心细节

1. Bean的作用域(Scope)

Spring允许你指定Bean的创建策略,核心作用域如下(默认是singleton):

作用域 说明
singleton 单例(默认):容器中只有1个Bean实例,所有请求都返回同一个对象
prototype 原型:每次调用getBean()或注入时,都创建新的Bean实例
request Web环境:每个HTTP请求创建1个Bean实例,请求结束后销毁
session Web环境:每个HTTP会话创建1个Bean实例,会话结束后销毁

使用方式 :通过@Scope注解指定:

java 复制代码
@Service
@Scope("prototype") // 原型作用域,每次获取都是新实例
public class UserService {
    // ...
}

2. Bean的生命周期(核心流程)

Spring容器创建Bean的完整流程,是理解Spring Core的关键:

bash 复制代码
flowchart TD
    A[实例化Bean] --> B[属性填充(DI注入依赖)]
    B --> C[初始化前(BeanPostProcessor前置处理)]
    C --> D[初始化(调用@PostConstruct/afterPropertiesSet)]
    D --> E[初始化后(BeanPostProcessor后置处理)]
    E --> F[Bean就绪(可被使用)]
    F --> G[容器关闭]
    G --> H[销毁前(调用@PreDestroy/destroy)]
    H --> I[销毁Bean]

代码示例(生命周期回调)

java 复制代码
@Service
public class UserService implements InitializingBean, DisposableBean {
    private final UserDao userDao;

    public UserService(UserDao userDao) {
        this.userDao = userDao;
        System.out.println("1. 构造器执行:创建UserService实例");
    }

    // 初始化回调1:@PostConstruct注解(推荐)
    @PostConstruct
    public void init() {
        System.out.println("4. @PostConstruct:初始化操作");
    }

    // 初始化回调2:实现InitializingBean接口(备选)
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("4. afterPropertiesSet:初始化操作");
    }

    // 销毁回调1:@PreDestroy注解(推荐)
    @PreDestroy
    public void preDestroy() {
        System.out.println("8. @PreDestroy:销毁前操作");
    }

    // 销毁回调2:实现DisposableBean接口(备选)
    @Override
    public void destroy() throws Exception {
        System.out.println("8. destroy:销毁前操作");
    }
}

3. 自定义Bean(@Bean注解)

对于第三方类(比如Druid数据源、RedisTemplate),无法加@Component注解,可通过@Bean手动注册Bean:

java 复制代码
@Configuration
public class SpringConfig {
    // 注册第三方类为Bean
    @Bean // 方法名默认是Bean名称,也可指定:@Bean("dataSource")
    public DruidDataSource dataSource() {
        DruidDataSource ds = new DruidDataSource();
        ds.setUrl("jdbc:mysql://localhost:3306/test");
        ds.setUsername("root");
        ds.setPassword("123456");
        return ds;
    }
}

总结

  1. 核心思想:Spring Core的核心是IoC(反转对象控制权)和DI(自动注入依赖),彻底解耦对象创建和依赖管理;
  2. 核心容器:ApplicationContext是实际开发的首选IoC容器(增强版BeanFactory),负责Bean的创建、注入、销毁;
  3. 核心用法:通过@Component/@Service等注解声明Bean,构造器注入实现依赖解耦,@Configuration+@Bean管理第三方类;
  4. 关键细节:Bean的作用域(默认单例)、生命周期(初始化/销毁回调)是理解Spring Core底层的核心。

Spring Core的这些特性是所有Spring扩展框架的基础------比如Spring Boot的自动配置、Spring MVC的Controller管理,本质都是基于Spring Core的IoC容器实现的。

相关推荐
悟能不能悟2 小时前
Spring HATEOAS 详细介绍
java·后端·spring
Leonardo_Fibonacci2 小时前
skbbs-day5
java·开发语言·mybatis
高山上有一只小老虎2 小时前
IDEA Community如何使用外置的tomcat
java·ide·intellij-idea
海南java第二人2 小时前
Java类加载机制深度解析:从双亲委派到自定义加载的完整指南
java·spring
努力也学不会java2 小时前
【Spring Cloud】初识Spring Cloud
运维·人工智能·后端·spring·机器学习·spring cloud
侧耳倾听1112 小时前
基准测试框架JMH
java·测试工具
草莓熊Lotso2 小时前
C++ 智能指针完全指南:原理、用法与避坑实战(从 RAII 到循环引用)
android·java·开发语言·c++·人工智能·经验分享·qt
better_liang2 小时前
每日Java面试场景题知识点之-Dubbo
java·dubbo·rpc框架·企业级开发
Qiuner2 小时前
Spring Boot AOP(五) 高级特性与源码实践
java·spring boot·后端