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();
    }
}
相关推荐
2601_96288572几秒前
如何用 Python 获取上证指数、沪深300、中证500 等指数行情?
开发语言·python
昔我往昔3 分钟前
LangChain_RAG_学习小结
后端·python
张张123y17 分钟前
后端第六课:Python 语法速通(0 基础入门,AI 应用开发的第一门语言)
开发语言·人工智能·python·ai·后端开发
小马不起床18 分钟前
Django 后端实战指南_10:用户扩展档案信息表
python·django·sqlite
Want59519 分钟前
Python跳动的爱心①
开发语言·python·数学建模
SamChan9021 分钟前
PDF 翻译后 1,250 变成 1.250,是错了吗?用 Python 核对数字格式
python·pdf·ocr·数据校验·文档翻译
Yolanda_202223 分钟前
30.利用GPU训练(一)
python
迅猛龙办公室32 分钟前
Python实现PM空气质量提醒
服务器·前端·python
神一样的老师38 分钟前
WS63 嵌入式 SSD1306 OLED 驱动单元测试实战
单元测试·log4j
骑着蜗牛撵大象3271 小时前
Spring AI + Qwen3.8 周报助手:从事项采集到人工确认卡的闭环实战
人工智能·spring·elasticsearch·自动化·大模型应用·qwen3.8·rag溯源