Spring Boot——@Autowired属性注入问题

这篇具有很好参考价值的文章主要介绍了Spring Boot——@Autowired属性注入问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🎈 @Autowired问题

当我们在使用@Autowired属性注入时,会发现idea提示Field injection is not recommended ,译为:不推荐使用属性注入
Spring Boot——@Autowired属性注入问题   要想了解Spring和idea之所以不推荐使用@Autowired属性注入,首先就要先了解Spring常用的注入方式:简单类型注入、集合类型注入, 域属性自动注入, 自动注入的类别, 空值注入, 构造注入。

在 Spring 中,常见的依赖注入方式有以下三种:

  1. Constructor Injection(构造函数注入):通过类的构造函数来注入依赖项。

  2. Setter Injection(setter 方法注入):通过类中的 setter 方法来注入依赖项。

  3. Field Injection(属性注入):通过直接在类的属性上使用注解来注入依赖项。

这三种方式各有优缺点,例如:

  • Constructor Injection 在单元测试中更易于模拟依赖项,可以提高代码的可测试性和可维护性。但是,当类的依赖项较多时,构造函数可能会变得很长,使得类的代码难以阅读和理解。

  • Setter Injection 使得依赖项可以在运行时动态修改,使用起来比较灵活方便。但是,使用 Setter Injection 的类可能会存在不完整的状态,如果必需的依赖项没有被设置,可能会导致运行时错误。

  • Field Injection 可以减少类的代码,使其更加简洁易懂。但是,当依赖项过多时,类的属性列表可能会变得很长,降低代码的可读性和可维护性。此外,由于依赖关系是通过类的属性直接注入的,容易出现一些难以发现的错误。

综上所述,建议在实际应用中优先使用 Constructor Injection 或 Setter Injection 来注入依赖项,以提高代码的可测试性和可维护性。Field Injection 应该谨慎使用,只有当属性较少且必需的依赖项很明显时才使用。

🎈 Spring中的三种依赖注入方式

💧 Field Injection

Field Injection(属性注入)是 Spring 中一种依赖注入方式,它使用 @Autowired@Inject 注解直接在属性上进行注入。例如:

@Service
public class UserServiceImpl implements UserService {
 
    @Autowired
    private UserRepository userRepository;
 
    // ...
}

在该例子中,UserServiceImpl 类中的 userRepository 属性通过 @Autowired 注入了 UserRepository 类型的 bean。

虽然 Field Injection 是一种简单方便的依赖注入方式,但也存在一些问题:

  1. 不利于单元测试:Field Injection 的方式使得测试时修改或替换依赖对象可能更加困难。因为需要通过反射机制才能访问和修改被注入的属性。

  2. 缺乏明确的依赖顺序:在类中使用 Field Injection 时,无法明确知道哪些依赖必须先注入,在什么顺序下注入。这可能导致一些潜在的问题。

  3. 难以发现错误:由于依赖关系是通过属性来注入的,容易出现拼写错误、类型错误等问题。这会导致运行时错误非常难以发现和定位。

因此,建议在应用程序中使用 Constructor Injection 或 Setter Injection 来代替 Field Injection,以达到更好的可测试性、可维护性和代码清晰度。

💧 Constructor Injection

Constructor Injection是构造器注入,它通过类的构造函数来注入依赖。例如:

@Service
public class UserServiceImpl implements UserService {
 
    private final UserRepository userRepository;
 
    @Autowired
    public UserServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
 
    // ...
}

在上面的示例中,UserServiceImpl 类中的依赖 userRepository 通过构造函数注入进来。

相比于 Field Injection,Constructor Injection 有以下优点:

  1. 明确的依赖关系:使用构造函数注入时,我们可以明确知道哪些依赖项是必须的,以及它们的顺序。这有助于消除代码中可能存在的歧义。

  2. 更好的可测试性:由于依赖被注入到类的构造函数中,因此在单元测试中可以更容易地模拟依赖项。

  3. 对不变性的支持:当类的依赖被注入后,它们通常是不变的。这使得类可以更好地支持不变性和线程安全性。

  4. 更好的代码清晰度:使用构造函数注入时,我们可以更清晰地看到类与其他组件之间的关系。这使得代码更易于阅读和理解。

在实践中,建议使用 Constructor Injection 作为首选方法来注入依赖项,以提高代码的可测试性和可维护性。

💧 Setter Injection

Setter Injection也会用到@Autowired注解,但使用方式与Field Injection有所不同,Field Injection是用在成员变量上,而Setter Injection的时候,是用在成员变量的Setter函数上。例如:

@Service
public class UserServiceImpl implements UserService {
 
    private UserRepository userRepository;
 
    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
 
    // ...
}

在上面的示例中,UserServiceImpl 类中的依赖 userRepository 通过 setter 方法注入进来。

相比于 Field Injection,Setter Injection 的主要优势是可以避免直接访问类的属性,而是通过 setter 方法来设置依赖项,从而实现更好的封装性。同时,使用 Setter Injection 的类可以动态地修改依赖项,这使得它们更加灵活。

但是,Setter Injection 也存在一些缺点。例如,使用 Setter Injection 的类可能会存在不完整的状态,如果必需的依赖项没有被设置,可能会导致运行时错误。此外,Setter Injection 使得代码更加分散,使用起来可能比 Constructor Injection 要更加繁琐。

因此,在使用 Setter Injection 时需要注意以下几点:

  1. 避免在类的构造函数中直接使用依赖项,而应该通过 setter 方法来设置依赖项。

  2. 设计 setter 方法时要确保参数非空,以避免在运行时出现 NullPointerException 错误。

  3. 在使用 Setter Injection 的类中,必需的依赖项应该在对象创建后尽早设置好,以避免出现不完整的状态。

总之,Setter Injection 是 Spring 中一种重要的依赖注入方式,使用它可以让代码更加灵活、封装性更好。但是,在使用 Setter Injection 时需要注意避免一些常见的陷阱,以确保代码的可测试性和可维护性。

🎈 三种依赖注入的对比

这三种注入方式各有优劣,下面我将对它们进行一些简单的对比。

  1. Constructor Injection(构造函数注入):

Constructor Injection 是一种通过类的构造函数来注入依赖项的方式。通过构造函数注入时,可以保证必需的依赖项在对象创建后立即可用,并且在创建对象的过程中就可以将依赖项完全实例化。

优点:使用构造函数注入可以非常明确地表达一个类的依赖关系,使得代码依赖性更加明显和易于维护。此外,由于所有必须的依赖项都必须在构造函数中声明,因此这种方式可以提高代码的可测试性。

缺点:当类的依赖项较多时,构造函数可能会变得很长,使得类的代码难以阅读和理解。此外,使用构造函数注入时必须额外定义构造函数,造成代码冗长。

  1. Setter Injection(setter 方法注入):

Setter Injection 是一种通过类中的 setter 方法来注入依赖的方式。这种注入方式比 Constructor Injection 更加灵活,因为 Setter Injection 允许在运行时动态更改依赖项。

优点:使用 Setter Injection 的类可以动态地修改依赖项,从而实现更好的灵活性。此外,Setter Injection 可以避免直接访问类的属性,从而实现更好的封装性。

缺点:使用 Setter Injection 的类可能会存在不完整的状态,如果必需的依赖项没有被设置,可能会导致运行时错误。此外,Setter Injection 使得代码更加分散,使用起来可能比 Constructor Injection 更加繁琐。

  1. Field Injection(属性注入):

Field Injection 是一种通过直接在类的属性上使用注解来注入依赖项的方式。这种注入方式可以使类的代码更加简洁,但也可能引发一些问题。

优点:Field Injection 能够减少类的代码,使其更加简洁易懂。此外,使用 Field Injection 的类可以直接访问依赖项,从而使代码更加紧凑。

缺点:Field Injection 的主要问题是它容易出现一些难以发现的错误。由于依赖关系是通过类的属性直接注入的,使用 Field Injection 可能会导致一些不必要的依赖项。此外,通过属性直接注入依赖项可能会违反单一责任原则。

综合比较:

注入方式 可靠性 可维护性 可测试性 灵活性 循环关系的检测 性能影响
Field Injection 不可靠 很灵活 不检测 启动快
Constructor Injection 可靠 不灵活 自动检测 启动慢
Setter Injection 不可靠 很灵活 不检测 启动快

总之,在使用三种依赖注入方式时,需要结合具体情况进行选择。在大多数情况下,Constructor Injection 和 Setter Injection 是比较常用和推荐的方式。同时,需要注意避免一些常见的陷阱,以确保代码的可测试性和可维护性。

🎈 属性注入解决方法

属性注入的问题:

  1. 基于属性注入的方式,违反单一职责原则​ 因为现在的业务一般都会使用很多依赖, 但拥有太多的依赖通常意味着承担更多的责任,而这显然违背了单一职责原则.并且类和依 赖容器强耦合,不能在容器外使用。
  2. 基于属性注入的方式,容易导致Spring 初始化失败​ 初始化Spring 容器是,由于属性在被注入前就引用而导致npe(空指针),进而导致容器初始化失败。​ java 在初始化一个类的顺序为,静态变量和静态代码块 -> 实例变量或者初始化语句 -> 构造函数 然后才会执行Spring 注解 @Autowired 自动装配依赖,所以在执行这个类的构造方法时,依赖属性还未被注入。
  3. @Autowired 是ByType注入,当存在两个类型相同的对象时就会注入失败

💧 @Resource

@Resource 是 Java EE 提供的一种注入方式,可以实现对其他组件(如 Bean、EJB 等)进行自动注入。在 Spring 中,@Resource 注解可以用来注入依赖项。

@Resource 注解默认按名称进行装配,可以指定其 name 属性显式指定要装配的 Bean 的名称。如果没有指定 name 属性,则会使用属性名作为 Bean 名称进行装配。如果找不到与 name 或属性名相匹配的 Bean,则会抛出 NoSuchBeanDefinitionException 异常。

下面是一个使用 @Resource 注解进行注入的示例:

@Service
public class UserService {
    public void addUser() {
        // ...
    }
}

@RestController
public class UserController {
    @Resource
    private UserService userService;

    @GetMapping("/addUser")
    public String addUser() {
        userService.addUser();
        return "Success";
    }
}

在上述示例中,@Resource 注解会自动注入 UserService 类型的 Bean。

需要注意的是,@Resource 注解和 @Autowired 注解类似,但存在一些细微的区别。例如,@Autowired 注解默认按类型进行装配,而 @Resource 注解默认按名称进行装配。此外,@Autowired 注解可以通过 @Qualifier 注解指定要装配的 Bean 的名称,而 @Resource 注解则直接使用 name 属性指定要装配的 Bean 的名称。因此,在使用 @Resource 注解时需要格外注意其装配方式和使用方法。

总之,在 Spring 中可以使用 @Resource 注解进行依赖注入,它可以根据名称或类型进行装配,提高了代码的灵活性和可维护性。

💧 @RequiredArgsConstructor

在 Spring 中,可以使用 @RequiredArgsConstructor 进行属性注入。这种方式可以帮助我们避免手动编写构造函数或繁琐的 setter 方法,同时还可以增加代码的可读性和可维护性。

在使用 @RequiredArgsConstructor 进行属性注入时,需要满足以下条件:

  1. 类中必须有 final 修饰的属性;
  2. 需要使用 lombok 插件。

下面是一个使用 @RequiredArgsConstructor 进行属性注入的示例:

@Service
@RequiredArgsConstructor
public class UserService {
    private final UserRepository userRepository;

    public User getUserById(Long id) {
        return userRepository.findById(id).orElse(null);
    }
}

在上述示例中,@RequiredArgsConstructor 注解会为 UserService 自动生成一个有参构造函数,并自动注入 final 修饰的 userRepository 属性。

需要注意的是,在使用 @RequiredArgsConstructor 进行属性注入时,我们应该尽可能地将依赖项声明为 final 属性。这样可以确保依赖项一旦被初始化就无法修改,增加代码的安全性和稳定性。

总之,@RequiredArgsConstructor 能够帮助我们简化代码,提高代码的可读性和可维护性。在实际开发中,可以根据具体情况合理使用 @RequiredArgsConstructor 进行属性注入。文章来源地址https://www.toymoban.com/news/detail-458076.html

到了这里,关于Spring Boot——@Autowired属性注入问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Spring】三大依赖注入(@Autowired,Setter,构造方法)

    目录 一、属性注入(@Autowired) 1.1 优点分析 1.2 缺点分析 1.2.1 无法实现final修饰的变量注入。 1.2.2 兼容性不好 1.2.3 (可能违背)设计原则问题 1.2.4 代码举例: 1.2.5 出现循环依赖该怎么办? 1.2.6 @Resource与@Autowired的区别 二、Setter注入 2.1 优点分析 2.2 缺点分析 2.2.1 不能注入不

    2024年02月01日
    浏览(42)
  • 了解Spring中的依赖注入:@Autowired vs. @Resource

    在Spring框架中,依赖注入是一项关键的特性,通过它,我们能够更灵活、更方便地管理和使用各种组件。在依赖注入的实现中, @Resource 和 @Autowired 是两个常用的注解,它们分别具有不同的特点和用途。在本篇博客中,我们将深入探讨这两个注解的功能、优缺点,并提供一些

    2024年02月02日
    浏览(55)
  • spring boot 3 + spring cloud sleuth 无法注入Tracer问题

    由于升级springboot版本到3.1.0后,导致原先的plumelog的traceId获取方式失败。 项目启动报错,无法找到tracer bean实例。 前往spring cloud sleuth官网,发现此项目已经迁移到别的项目,也就是说引入的依赖不单单只是引入spring-cloud-starter-sleuth组件,还要引入其他依赖 在此贴下完整的项

    2024年02月07日
    浏览(30)
  • 【Spring Boot `@Autowired` Annotation】

    在Spring Boot中, @Autowired 注解用于自动装配bean。默认情况下,它按照类型进行装配。当存在多个相同类型的bean时,就会出现以下错误: 这种情况下,Spring无法明确选择哪个bean进行注入,因为存在多个匹配项。 解决这个问题有几种方式: 1. 使用 @Qualifier 注解 结合 @Qualifier 注

    2024年03月13日
    浏览(40)
  • 使用@Component时再使用@Resource或@Autowired时注入失败问题

    在 @Component 注解的类下,再使用了 @Resource 或 @Autowired 注解。如此操作会导致依赖注入失败。 这是因为spring加载它们的顺序不同,在使用 @Component 注解将bean实例化到spring容器内的时候,因为 @Autowired 是在这个bean之中的,此时 @Autowired 还未完成自动装载,所以导致依赖注入的

    2024年02月06日
    浏览(38)
  • 【注解使用】使用@Autowired后提示:Field injection is not recommended(Spring团队不推荐使用Field注入)

    在使用 IDEA 开发 SpringBoot 项目时,在  Controller  类中使用注解  @Autowired  注入一个依赖出现了警告提示,查看其他使用该注解的地方同样出现了警告提示。这是怎么回事?由于先去使用了SpringBoot并没有对Spring进行系统性学习,所以做一个记录。 Field injection is not recommended(

    2024年02月12日
    浏览(40)
  • 关于在 springboot 中使用 @Autowired 注解来对 TemplateEngine 进行自动装配时,无法注入的问题。

    本文是基于江南一点雨的 Spring Boot+Vue 系列视频教程第 三 章的第三节,详情参考Spring Boot+Vue系列视频教程 在观看学习这一节时,发现当进行手动渲染 Thymeleaf 模板时,通过 @Autowired 注解来对 TemplateEngine 进行自动装配时,发现 idea 对其显示 No beans of \\\'TemplateEngine \\\' type of found。

    2024年02月02日
    浏览(49)
  • Spring Boot中的依赖注入和自动注入

    以下内容为本人学习 Spring Boot的依赖注入和自动注入 与ChatGpt提问后对其回答 进行部分修改 (有的错误实在是离谱 = =)、格式调整等操作后的答案, 可能对于其中部分细节(是错是对,能力有限有的看不出来 = =),并未做深入探究 ,大家感兴趣的话可以自行验证。 依赖注

    2024年02月06日
    浏览(47)
  • mini-spring-为bean填充属性&注入bean

    bean属性填充的设计 什么是属性填充 属性填充可以在类 AbstractAutowireCapableBeanFactory 的 createBean 方法中添加补全属性方法。 属性填充要做的事情 1.属性填充要在类实例化创建之后,也就是需要在 AbstractAutowireCapableBeanFactory 的 createBean 方法中添加 applyPropertyValues 操作。由于我们需

    2024年01月25日
    浏览(36)
  • 【Spring Boot Bean 注入详解】

    什么是 Bean 注入? 在 Spring 中,Bean 是应用程序的核心构建块。Bean 是由 Spring IoC 容器管理的对象,通过依赖注入实现对象之间的解耦。 Spring Boot 中的 Bean 注入 在 Spring Boot 中,Bean 注入通常通过 @Autowired 、 @Component 、 @Service 、 @Repository 等注解实现。 @Autowired 用于自动装配

    2024年02月21日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包