Spring:如何避免将构造函数注入与自动连接的字段组合在一起

bejyjqdl  于 2023-02-15  发布在  Spring
关注(0)|答案(3)|浏览(144)

避免同时使用构造函数和字段注入的最佳选择是什么?
据我所知,不推荐使用字段注入,而构造函数才是最好的方法。
请在下面查找在@Configuration bean中创建类A和在类A中创建类B作为构造函数参数的地方。
然而,类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;  
}
anhgbhbe

anhgbhbe1#

一般来说,@Autowired注解已经出现在Spring 2.5中,后来在Spring 3.0中,他们引入了“Java DSL”用于配置,即使用@Configuration注解和@Bean注解方法进行配置的方式。
如果像在类A的示例中那样使用@Configuration,那么实际上不必使用@Autowired,如果通过@Configuration管理所有内容,也不需要像@Component这样的注解。
因此,假设您不确定如何将BC之类的类注入到A类中而不进行自动连接,假设类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和/或C是在不同的@Configuration文件中定义的或通过@Component注解定义的,则此方法将不起作用
注意,类A没有任何Autowired字段,所有内容都是通过构造函数注入的。基本上,类A现在根本没有任何与spring相关的注解。
现在,例如,如果您不使用BC的配置,您仍然可以将@Component放在它们上面,并且这仍然有效,因为Spring“收集”关于应该创建什么bean的信息,并且它有多个资源来“获得”这种信息:通过用@Component注解的类的类扫描、通过配置中定义的@Bean-s等等。
即使你不管理类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 {
}
voase2hg

voase2hg2#

@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;
}
gzszwxb4

gzszwxb43#

你的例子有点难以理解,因为它缺少上下文。
总体来说:字段注入在存储库、服务或控制器等Singelton组件上是坏的。
不知何故,你的例子有点难以效仿,但有一个模式对我很有效:

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

所以你必须照顾好那些字段,甚至编译器也会告诉你是否出了问题...

相关问题