Spring @Autowire on Properties vs Constructor
因此,由于我一直在使用Spring,如果要编写一个具有依赖性的服务,我将执行以下操作:
1 2 3 4 | @Component public class SomeService { @Autowired private SomeOtherService someOtherService; } |
我现在遇到了使用另一个约定来实现相同目标的代码
1 2 3 4 5 6 7 8 9 | @Component public class SomeService { private final SomeOtherService someOtherService; @Autowired public SomeService(SomeOtherService someOtherService){ this.someOtherService = someOtherService; } } |
号
这两种方法都有效,我理解。但是使用选项B有什么好处吗?对我来说,它在类和单元测试中创建了更多的代码。(必须编写构造函数,不能使用@injectmocks)
我有什么东西不见了吗?除了向单元测试中添加代码之外,自动布线的构造函数还有其他功能吗?这是进行依赖项注入的一种更可取的方法吗?
是的,方案B(称为构造器注入)实际上是相对于现场注入而推荐的,它有几个优点:
- 这些依赖关系是明确的。在任何其他情况下(比如在配置类中显式创建bean实例)测试或实例化对象时,都无法忘记一个实例。
- 依赖关系可以是最终的,这有助于健壮性和线程安全性。
- 您不需要反射来设置依赖项。InjectMock仍然可用,但不是必需的。您只需自己创建模拟并通过简单地调用构造函数来注入它们。
请参阅这个博客文章,以获取一篇更详细的文章,作者是Spring的一位撰稿人OlivierGierke。
我将用简单的语言向您解释:
在选项(a)中,您允许任何人(在Spring容器外部/内部的不同类中)使用默认的构造函数(如
Is there anything else the autowired constructor does besides add code
to the unit tests? Is this a more preferred way to do dependency
injection?
选项(b)是首选方法,因为它不允许在没有实际解决
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public class SuperSomeService { private String name; public SuperSomeService(String name) { this.name = name; } } @Component public class SomeService extends SuperSomeService { private final SomeOtherService someOtherService; private Map<String, String> props = null; @Autowired public SomeService(SomeOtherService someOtherService){ SuperSomeService("SomeService") this.someOtherService = someOtherService; props = loadMap(); } } |
好知
如果只有一个构造函数调用,则不需要包含@autowired注释。然后您可以使用类似的方法:
1 2 3 4 5 6 7 8 9 | @RestController public class NiceController { private final DataRepository repository; public NiceController(ChapterRepository repository) { this.repository = repository; } } |
…Spring数据存储库注入示例。