当前位置: 首页 > news >正文

Spring(三)容器-注入

一 自动注入@Autowire

代码实现:

package org.example.spring01.service;

import org.springframework.stereotype.Service;


@Service
public class UserService {

}
package org.example.spring01.controller;

import lombok.Data;
import lombok.ToString;
import org.example.spring01.bean.Person;
import org.example.spring01.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import java.util.List;
import java.util.Map;

@ToString
@Data
@Controller
public class UserController {
    /**
     * 自动注入 原理:Spring调用容器的getBean方法
     * @Autowired
     * 只有且只找到一个,直接注入,名字无所谓
     * 如果找到多个在按照名称去找,变量名就是名字
     */

    @Autowired
    UserService userService;

    @Autowired
    List<Person> personList;

    @Autowired
    Map<String,Person> personMap;

}
package org.example.spring01;


import org.example.spring01.controller.UserController;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class Spring01Application {

    public static void main(String[] args) {
        // 启动springboot应用
        ConfigurableApplicationContext ioc = SpringApplication.run(Spring01Application.class, args);
        System.out.println("run = " + ioc);

        UserController bean = ioc.getBean(UserController.class);
        System.out.println("bean = " + bean);
    }
}

默认首选/指定Bean@Primary @Qualifier

1 概述:

  • @Primary“默认选我”,简化多数场景的依赖注入。

  • @Qualifier“点名要谁”,精准控制依赖的选择。

2 当某个 Bean 被标记为 @Primary,Spring 的依赖注入规则变为:

  1. 优先选择 @Primary 的 Bean,无论字段名如何变化。

  2. 忽略属性名匹配,直接注入 @Primary 标记的 Bean。

3 在没有 @Primary 时,Spring 按以下顺序解决依赖:

  1. 按类型匹配:寻找与字段类型一致的 Bean。

  2. 按名称匹配:如果有多个同类型 Bean,尝试将字段名与 Bean 的名称(ID)匹配。

@Primary标记一个Bean,然后在注入时用@Autowired,这时候会自动选择@Primary的;或者当有多个Bean时,用@Qualifier指定名称来注入。

当同时存在 @Primary 和 @Qualifier 时,@Qualifier 的优先级更高:

代码实现:

    // @Primary默认组件,不说明Person具体就是这个
    @Primary
    @Bean("LiSi")
    public Person lisi() {
        Person person = new Person();
        person.setAge(18);
        person.setGender("男");
        person.setName("李四");
        return person;
    }

代码实现:

package org.example.spring01.service;

import lombok.Data;
import org.example.spring01.bean.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;


@Data                // Lombok 注解,自动生成 getter/setter/toString 等方法
@Service             // Spring 注解,标记为服务层 Bean
public class UserService {

    //如果容器中这种组件有多个,则使用@Qualifier注解精确指定注入的组件名
    @Qualifier("ZhangSan")  // 指定注入名为 "ZhangSan" 的 Bean
    @Autowired               // 自动注入依赖
    Person person;           // 依赖的 Person 对象
}

三 自动注入@Resource

在选择使用哪一个注解时,可以根据项目的具体需求和个人偏好来决定。在许多情况下,这两种注解可以互换使用,特别是在只有一个符合条件的bean的情况下。

使用场景:

  • 如果项目完全基于Spring框架,那么@Autowired可能是更自然的选择;
  • 而如果是在Java EE环境中,或者你更倾向于通过名称来引用bean,那么@Resource可能更适合。

参数

  • @Autowired 支持一个 required 参数,默认值为 true。设置为 false 时,表示即使没有找到对应的bean也不会报错。
  • @Resource 支持 name 和 type 属性,可以明确指定要注入的bean的名称和类型。

注入方式

  • @Autowired 支持构造器注入、设值方法注入以及字段注入。
  • @Resource 主要用于字段注入和设值方法注入,不直接支持构造器注入。

四 构造器注入

在 Spring 框架中,构造器自动注入(Constructor Injection) 是一种通过类的构造方法(Constructor)自动注入依赖项的方式。它不仅是依赖注入(DI)的核心模式之一,更是 Spring 官方推荐的最佳实践。以下是其核心概念、优势及使用场景的详细解析:

1. 什么是构造器注入?

  • 定义:通过类的构造方法参数传递依赖项,由 Spring 容器自动将匹配的 Bean 注入到参数中。

  • 自动注入:从 Spring 4.3 开始,如果类只有一个构造方法,@Autowired 注解可以省略,Spring 会默认使用该构造方法注入依赖。

@Service
public class UserService {
    private final UserRepository userRepository;
    private final EmailService emailService;

    // Spring 自动注入依赖(无需 @Autowired)
    public UserService(UserRepository userRepository, EmailService emailService) {
        this.userRepository = userRepository;
        this.emailService = emailService;
    }
}

2、构造器注入的优势

1. 依赖不可变性

  • final 字段:依赖项通过构造方法赋值后,可以声明为 final,确保对象初始化后不可变。

  • 线程安全:避免依赖在运行时被意外修改,提升代码健壮性。

2. 明确依赖关系

  • 强制依赖:构造方法参数明确声明了类的所有必需依赖,避免依赖缺失。

  • 启动时检查:如果 Spring 容器中缺少某个依赖,应用会在启动时直接报错(而非运行时才暴露问题)。

3. 避免循环依赖

  • 设计约束:如果两个类通过构造器注入相互依赖,Spring 会直接抛出 BeanCurrentlyInCreationException,迫使开发者重构代码,解决循环依赖问题。

4. 更好的测试性

  • 无需容器:在单元测试中,可以直接通过构造方法传入 Mock 对象,无需依赖 Spring 容器或反射。

  • 代码透明:依赖关系一目了然,便于理解类的职责。


3、使用场景

1. 强依赖场景

  • 类的核心功能依赖某个组件(如数据库访问层 UserRepository)。

  • 示例:服务类、控制器、数据访问对象(DAO)。

2. 需要不可变对象的场景

  • 配置类、DTO(数据传输对象)、工具类等,确保依赖不会被修改。

3. Spring Boot 项目

  • Spring Boot 强烈推荐构造器注入,尤其是在结合 Lombok 的 @RequiredArgsConstructor 时,可以大幅简化代码。


4、实现方式

1. 隐式自动注入(Spring 4.3+)

  • 如果类只有一个构造方法,Spring 会自动选择它进行注入,无需 @Autowired

@Service
public class PaymentService {
    private final PaymentGateway paymentGateway;

    // 无需 @Autowired
    public PaymentService(PaymentGateway paymentGateway) {
        this.paymentGateway = paymentGateway;
    }
}

2. 显式指定构造方法

  • 如果类有多个构造方法,需用 @Autowired 指定使用哪一个。

@Service
public class OrderService {
    private final InventoryService inventoryService;
    private final Logger logger;

    @Autowired // 显式标记要使用的构造方法
    public OrderService(InventoryService inventoryService) {
        this(inventoryService, LoggerFactory.getLogger(OrderService.class));
    }

    // 辅助构造方法
    public OrderService(InventoryService inventoryService, Logger logger) {
        this.inventoryService = inventoryService;
        this.logger = logger;
    }
}

3. 结合 Lombok 简化代码

  • 使用 @RequiredArgsConstructor 自动生成包含 final 字段的构造方法。

@Service
@RequiredArgsConstructor // 自动生成构造方法
public class NotificationService {
    private final EmailService emailService;
    private final SmsService smsService;
}

相关文章:

  • 玩转大模型——Trae AI IDE国内版使用教程
  • 【我的Android进阶之旅】如何使用NanoHttpd在Android端快速部署一个HTTP服务器?
  • GPU、NPU与LPU:大语言模型(LLM)硬件加速器全面对比分析
  • 20241130 RocketMQ本机安装与SpringBoot整合
  • CSS2.1基础学习
  • STM32——DMA详解
  • 似然函数与极大似然估计
  • 表达式求值(后缀表达式)
  • 软考中级-数据库-3.2 数据结构-数组和矩阵
  • Deepgram推出Nova-3 Medical,AI语音转录助力医疗行业
  • 基于CURL命令封装的JAVA通用HTTP工具
  • Linux中shell对话框(dialog)编程
  • 从零开始学习Slam--数学概念
  • 文心4.5,大模型下半场的野心之作
  • 网络学习(四)HTTPS中,SSL的单向认证与双向认证
  • [自然语言处理]pytorch概述--什么是张量(Tensor)和基本操作
  • Sourcetrail 代码分析工具
  • 年后寒假总结及计划安排
  • Linux 下使用traceroute来进行网络诊断分析
  • css之英文换行样式
  • 网站运营部的职责/百度文章收录查询
  • 网站建设如何开单/自己如何做网站
  • 怎么选择合肥网站建设/关键词举例
  • 做网站算运营吗/每日一则小新闻
  • 怎么提高网站流量/搜狗站长管理平台
  • 哈尔滨手机网站建设/推广方案怎么做