Spring:如何避免将构造函数注入与自动装配字段结合使用

Spring :how to avoid combining constructor injection with autowired fields

避免构造函数和字段注入的最佳替代方法是什么?

据我了解,不建议使用字段注入,构造函数是可行的方法。 (http://olivergierke.de/2013/11/why-field-injection-is-evil/)

请在下面找到我的场景,其中 class A 在 @Configuration bean 中创建,新 B() 作为构造函数参数。

但是 class A 也需要其他 bean 来操作,例如 C/D/E,后者又具有自己的自动装配依赖项。对如何在此处应用最佳推荐方法感到困惑。

有什么建议,请告诉我。

@Configuration 
class Config
{
  @Bean
  public A create_A(){
    A = new A(new B());
  }

}

class A {
B b;

@Autowired
C c;
@Autowired
D d;
@Autowired
E e;


        A(B b) {
            this. b= b;
         }

}


class C{

@Autowired 
  Y y;
  
  }

您的示例有点难以理解,因为它缺少上下文。

总体而言:字段注入在存储库、服务或控制器等 Singelton 组件上很糟糕。

不知何故,你的例子有点难以理解,一个对我有用的模式:

  • 使应通过 C'tor 注入的字段成为最终字段
  • 用相应的Spring 构造型(@Component、@Service...)注释类

所以你必须处理这些字段,甚至编译器会告诉你是否出现问题...

@Bernd 确实回答了这个问题,但我想包含一些代码以使其更清楚

@Component
class B{
    // what ever it is
}

@Component
class A {

private final B b;
private final C c;
private final D d;
private final E e;

@Autowired
A(B b, C c, D d, E e) {
    this.b= b;
    this.c = c;
    this.d = d;
    this.e = e;
    }

}

@Component
class Y{
    // what ever it is
}

@Component
class C{
private final Y y;

@Autowired
C(Y y){
    this.y = y;
}

总的来说,@Autowired注解出现在Spring 2.5中,后来在Spring 3.0中他们引入了“Java DSL”进行配置,方式配置 @Configuration 注释和 @Bean 注释方法。

如果您像 class A 示例中那样使用 @Configuration,那么您实际上不必使用 @Autowired。如果您通过 @Configuration.

管理所有内容,您也不需要像 @Component 这样的注释

因此,假设您怀疑如何在不自动装配的情况下将 class 注入 BC 到 class A 中,假设 class A 是通过 @Configuration 定义的,您可以执行以下操作:

@AllArgsConstructor // I've used lombok - it will create a constructor with B and C for you, but you can define the constructor in java as well
public class A {
   private final B b; 
   private final C c;
   ...
}


@Configuration
public class MyConfiguration {
   @Bean
   public A a(B b, C c) {
       return new A(b,c);
   }

   @Bean
   public B b() {
      return new B();
   }

   @Bean
   public C c() {
      return new C();
   }

}

另一种方法是在 @Configuration:

中使用显式方法调用
@Configuration
public class MyConfiguration {
   @Bean
   public A a() {  // note, as opposed to the previous example, no parameters here
       return new A(b(),c()); // note the explicit calls
   }

   @Bean
   public B b() {
      return new B();
   }

   @Bean
   public C c() {
      return new C();
   }

}

但是如果 B and/or C 在不同的 @Configuration 文件中或通过 @Component 注释定义[=38],此方法将不起作用=]

请注意,class A 没有任何自动装配字段,所有内容都是通过构造函数注入的。基本上 class A 现在根本没有任何 spring 相关的注释。

现在,如果您不使用 BC 的配置,例如,您仍然可以将 @Component 放在它们上面,这仍然有效,因为 Spring“收集”有关应创建哪些 bean 的信息,并且它有多种资源来“获取”此类信息:通过 class 扫描 class 用 @Component 注释的 es,通过配置中定义的 @Bean-s,等等。

即使您不管理 class A 构造函数注入仍然有效:

@Component
@AllArgsConstructor // if there is only one constructor in the class, spring will use it for autowiring automatically, so no need to put @Autowired even on the constructor for recent spring versions
class A {
  private final B b;
  private final C c;
}

@Component
class B {
}

@Component 
class C {
}