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();
    }
}
相关推荐
默_笙4 天前
🍙 给每个请求过安检:FastAPI 是怎么把校验写进类型注解的
python
qq_426003964 天前
启动playwright录制codegen生成自动化测试脚本
python·自动化
虎头金猫4 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
长沙三为智能科技4 天前
家政小程序开发从0到上线:五阶段交付流程与验收清单
python
伞伞悦读4 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
只睡四小时4 天前
Canvas 弹道联机实战:700 行 + 固定时间步长
python·websocket·html5·游戏开发·canvas
吧啦蹦吧4 天前
替换11111
log4j
奇思妙想聪明勤奋的小羊4 天前
DeepAgents第5章:子Agent 与上下文隔离—让 Agent学会委派
人工智能·python·学习·语言模型
lpfasd1234 天前
2026年第38周GitHub趋势周报
python·科技·github
IZero074 天前
Jev 与 Laya
python·语言模型