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();
    }
}
相关推荐
维克兜率天7 小时前
【维克】复合型CTA:趋势+套利的双轮驱动
python·学习方法
伞伞悦读7 小时前
【第76期】两张3行表左连接变5行:主键、validate与未匹配排查完整教程
人工智能·python
用户8356290780518 小时前
使用 Python 在 Excel 中添加和自定义迷你图
后端·python
用户8356290780518 小时前
使用 Python 在 Excel 图表中添加趋势线与回归方程
后端·python
SL_staff8 小时前
从配置失效到逻辑复用:JVS-Logic 如何构建可治理的业务编排中枢
java·spring·产品
特立独行的猫A8 小时前
一份 Markdown 发十个平台:cspub 一稿多投
java·后端·python
深蓝AI8 小时前
HTTPX 超时 1 秒,接口为何还能跑 2.4 秒?
python
CyrusYiVPP9 小时前
哪个用户会再来买?RFM模型+plotly画出用户分层,数据分析实战第2期
人工智能·python
李帅51510 小时前
用 CPU 做发票识别:从 OCR 文本行到结构化明细表的 4 个硬骨头
python
happylifetree11 小时前
Python79:核心语法-面向对象基础-实例方法
python