因此,由于我一直在使用Spring,如果我要编写一个有依赖关系的服务,我会这样做:

@Component
public class SomeService {
     @Autowired private SomeOtherService someOtherService;
}

我现在遇到了使用另一种约定来实现相同目标的代码

@Component
public class SomeService {
    private final SomeOtherService someOtherService;

    @Autowired
    public SomeService(SomeOtherService someOtherService){
        this.someOtherService = someOtherService;
    }
}

我知道这两种方法都有效。但是选择B有什么好处吗?对我来说,它在类和单元测试中创建了更多的代码。(必须写构造函数,不能使用@InjectMocks)

我遗漏了什么吗?除了将代码添加到单元测试之外,自动连接构造函数还有其他功能吗?这是一种更可取的依赖注入方式吗?


当前回答

有一种方法可以使用Lombok中的@ requeiredargsconstructor注释通过构造函数注入依赖项

@RequiredArgsConstructor
@Service
 class A {
     private final B b // needs to be declared final to be injected
}

这样就不需要指定构造函数

其他回答

很高兴知道

如果只有一个构造函数调用,则不需要包含@Autowired注释。然后你可以使用这样的语句:

@RestController
public class NiceController {

    private final DataRepository repository;

    public NiceController(ChapterRepository repository) {
        this.repository = repository;
    }
}

... Spring数据存储库注入的例子。

有一种方法可以使用Lombok中的@ requeiredargsconstructor注释通过构造函数注入依赖项

@RequiredArgsConstructor
@Service
 class A {
     private final B b // needs to be declared final to be injected
}

这样就不需要指定构造函数

我用简单的话来解释:

在选项(A)中,您允许任何人(在Spring容器外部/内部的不同类中)使用默认构造函数创建实例(如new SomeService()),这并不好,因为您需要SomeOtherService对象(作为依赖项)用于您的SomeService。

除了添加代码,自动连接构造函数还有其他功能吗 单元测试?这是一种更受欢迎的依赖方式吗 注射吗?

选项(B)是首选方法,因为它不允许在没有实际解决SomeOtherService依赖关系的情况下创建SomeService对象。

事实上,根据我的经验,第二种选择更好。不需要@Autowired。事实上,更明智的做法是创建与框架耦合不太紧密的代码(就像Spring一样)。您希望代码尽可能采用延迟决策方法。这是尽可能多的pojo,以至于框架可以很容易地交换出来。 所以我建议你创建一个单独的Config文件,并在那里定义你的bean,如下所示:

在somesservice .java文件中:

public class SomeService {
    private final SomeOtherService someOtherService;

    public SomeService(SomeOtherService someOtherService){
        this.someOtherService = someOtherService;
    }
}

在ServiceConfig.java文件中:

@Config
public class ServiceConfig {
    @Bean
    public SomeService someService(SomeOtherService someOtherService){
        return new SomeService(someOtherService);
    }
}

事实上,如果你想深入了解它的技术,使用字段注入(@Autowired)会产生线程安全问题(以及其他问题),这显然取决于项目的大小。检查这来了解更多的优点和缺点的自动装配。实际上,关键的人建议你使用构造函数注入而不是字段注入

请注意,自从Spring 4.3以来,你甚至不需要在你的构造函数上使用@Autowired,所以你可以用Java风格编写代码,而不是绑定到Spring的注释上。 你的代码片段看起来像这样:

@Component
public class SomeService {
    private final SomeOtherService someOtherService;

    public SomeService(SomeOtherService someOtherService){
        this.someOtherService = someOtherService;
    }
}