Spring Bean 依赖注入

在 Spring 中,自动化装配和显式 Java 配置装配是两种核心方式。下面分别说明。


一、自动化装配

自动化装配包含两个步骤:

  1. 组件扫描:Spring 自动发现上下文中的 Bean

  2. 自动装配:Spring 自动满足 Bean 之间的依赖

1. 创建可被发现的 Bean

使用 @Component 注解标记一个类:

java 复制代码
@Component
public class UserService {
    public void save() {
        System.out.println("保存用户");
    }
}

2. 开启组件扫描

Java 配置类

java 复制代码
@Configuration
@ComponentScan(basePackages = "com.example.service")
public class AppConfig {
}

Spring Boot 自动扫描(在主类上)

java 复制代码
@SpringBootApplication  // 内含 @ComponentScan
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

3. 自动装配依赖

使用 @Autowired

java 复制代码
@Component
public class UserController {
    @Autowired
    private UserService userService;

    public void handle() {
        userService.save();
    }
}

也可以用在构造器(推荐,方便单元测试):

java 复制代码
@Component
public class UserController {
    private final UserService userService;

    @Autowired  // 只有一个构造器时可省略
    public UserController(UserService userService) {
        this.userService = userService;
    }
}

4. 处理歧义性

当多个 Bean 实现同一接口时,用 @Primary@Qualifier

java 复制代码
@Component
@Primary  // 优先使用
public class DataSourceA implements DataSource {}

@Component
@Qualifier("dataSourceB")
public class DataSourceB implements DataSource {}

使用处指定:

java 复制代码
@Autowired
@Qualifier("dataSourceB")
private DataSource dataSource;

二、通过 Java 代码装配 Bean(显式配置)

适合:第三方类库、无法加注解的类、需要复杂初始化逻辑的 Bean。

1. 基本用法

java 复制代码
@Configuration
public class AppConfig {

    @Bean
    public UserService userService() {
        return new UserService();
    }
}

@Bean 告诉 Spring:该方法返回一个对象,应注册为 Spring 应用上下文中的 Bean。

2. 注入依赖

方式一:方法调用(简洁)

java 复制代码
@Bean
public UserController userController() {
    return new UserController(userService());
}

方式二:方法参数注入(推荐,更灵活)

java 复制代码
@Bean
public UserController userController(UserService userService) {
    return new UserController(userService);
}

Spring 会自动从上下文中找到 UserService 类型的 Bean 传入。

3. 复杂初始化示例

java 复制代码
@Bean
public DataSource dataSource() {
    HikariConfig config = new HikariConfig();
    config.setJdbcUrl("jdbc:mysql://localhost:3306/test");
    config.setUsername("root");
    config.setPassword("123456");
    return new HikariDataSource(config);
}

4. 混合使用

Java 配置中可以引用通过 @Component 扫描得到的 Bean:

java 复制代码
@Configuration
@ComponentScan("com.example.service")
public class AppConfig {

    @Bean
    public ReportService reportService(UserService userService) {
        // userService 来自组件扫描
        return new ReportService(userService);
    }
}

三、对比总结

特性 自动化装配 (@Component + @Autowired) Java 显式配置 (@Configuration + @Bean)
适用场景 自己编写的类 第三方类、复杂初始化、需要控制实例化次数
代码侵入性 有(需要加注解) 无侵入
灵活性 一般 很高(可写任意初始化逻辑)
推荐原则 优先使用自动化(约定优于配置) 自动化无法满足时使用

四、完整小示例

java 复制代码
@Component
public class UserService {
    public void save() {
        System.out.println("User saved");
    }
}

@Configuration
@ComponentScan("com.example")
public class JavaConfig {
    // 可额外定义 @Bean
}

public class Main {
    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);
        UserService service = ctx.getBean(UserService.class);
        service.save();
    }
}
相关推荐
Lyn_Li9 小时前
扫描 PDF 歪了怎么办?用 6 种检测方法做本地批量扶正(附开源工具)
python·pdf·ocr·tesseract·开源工具·文档处理·本地处理·扫描件纠偏
金銀銅鐵10 小时前
费马小定理
python·数学·算法
疋瓞14 小时前
python和C++对比(1)_数据类型和数据结构
数据结构·c++·python
如此这般英俊15 小时前
手搓Claude Code-第六章 subagent
数据结构·人工智能·python·语言模型·自然语言处理
元Y亨H16 小时前
Python - FastAPI 全方位介绍
python·fastapi
error:(17 小时前
【系统与实战双精通】VS Code 调试 ROS2 Python 节点与 Launch 系统指南
android·java·python
weigangwin17 小时前
LlamaIndex 第一次试用:别先写 RAG Demo,先验上下文合同
python·ai·agent·rag·检索·llamaindex·观测性
省四收割者17 小时前
一文详解信号完整性(1)
python·嵌入式硬件·数学建模·信息与通信·信号处理·智能硬件
AI人工智能+电脑小能手18 小时前
【大白话说Java面试题 第155题】【06_Spring篇】第15题:Spring 如何解决循环依赖问题?
java·spring·循环依赖·三级缓存·aop代理
ai生成式引擎优化技术18 小时前
从知识连接到智能组织:WSaiOS认知网络的理论框架与系统设计摘要
网络·python·plotly·django·pygame