春季现场注入的内部工作以及为啥不建议使用

Posted

技术标签:

【中文标题】春季现场注入的内部工作以及为啥不建议使用【英文标题】:Internal working of field injection in spring and why is it not recommended to use春季现场注入的内部工作以及为什么不建议使用 【发布时间】:2020-10-27 16:17:24 【问题描述】:

正如标题所暗示的,我想知道字段注入在春季内部是如何工作的,我阅读了很多关于此的文章并了解了一些类似下面的内容,但不了解其背后的确切原因:

-> 不应该使用它,因为当你进行单元测试时,你依赖于 spring 在字段注入的情况下实例化类的容器。

-> 在字段注入的情况下不能使用“final”关键字,这意味着你不能使字段不可变。

-> 内部使用反射

我想知道@Autowired 在内部究竟是如何工作的,它是如何使用反射的,我试图了解上述所有要点背后的确切原因,当我们编写以下代码时,幕后会发生什么:

@Component
public class B 

    @Autowired
    private A a1;


我已阅读有关此主题的堆栈溢出的类似问题,但找不到我正在寻找的确切解释。

【问题讨论】:

详细解释发生的事情将解释应用程序上下文生命周期是如何工作的。您已经有了 3 件不应该这样做的事情,还有一件更紧迫的事情,它隐藏了您需要(强制)依赖项才能使用该对象的事实。在执行new YourService() 并且它需要 3 个存储库时,您根本不知道并阻止您实际编写单元测试(这导致您的第一个原因,您需要容器技术来确定要注入的内容)。 请链接到您阅读过的类似问题。 【参考方案1】:

Spring 有一个 Bean 后处理器的概念。

当 spring 构建一个 bean 时,它会应用已注册的 bean 后处理器来帮助“初始化”bean。

所以,org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor 处理自动装配。

基本上它适用于新创建的对象。 Spring 内省 bean 的字段(通过使用反射)。具有@Autowired 的字段是使用此 bean 后处理器处理的主题。它在应用程序上下文中找到注入的候选对象并实际注入该值。

现在有了这些信息,为什么不能自动装配最终字段是可以理解的。不用管 spring,在纯 Java 中,final 字段必须在声明期间(final int i = 123)或类的构造函数中直接实例化。但是自动装配发生在构造函数之后,因此不可能自动装配最终字段。

对于单元测试,私有属性必须以某种方式从测试中配置。但是由于它们是封装的(是的,在这种情况下,spring 打破了封装以供其使用),因此不可能为包含字段注入的类编写一个好的测试。这就是切换到构造函数注入的原因。

public class FieldInjection 
   @Autowired
   private A a;

VS.

public class ConstructorInjection 

   private final A a;

   // this can be generated by lombok, you don't have to put @Autowired on constructor in the case of single constructor, spring will use it to create a bean
   public ConstructorInjection(A a) 
      this.a = a; 
   

现在无法测试 FieldInjection 类:


public class FieldInjectionTest 

   @Test
   void test() 
      FieldInjection underTest = new FieldInjection();
      how do you know that you should instantiate A a.  ???? 
   


但是,在构造函数注入的情况下,这是一项微不足道的任务:

public class ConstructorInjectionTest 

   @Test
   void test() 
     A a = mock(A.class);
     ConstructorInjection underTest = new ConstructorInjection(a); 
     // the dependencies must be supplied in the constructor 
     // otherwise its impossible to create an object under test
   

【讨论】:

以上是关于春季现场注入的内部工作以及为啥不建议使用的主要内容,如果未能解决你的问题,请参考以下文章

实时 Web 应用程序使用啥以及为啥?需要解释和小型现场演示[关闭]

公开课预告:利用webtransport进行现场视频流注入

今晚公开课:利用webtransport进行现场视频流注入

利用WebTransport进行现场视频流注入

利用WebTransport进行现场视频流注入

第十五届北京师范大学程序设计竞赛现场决赛题解