英文:
Is declaring multiple instances of the same class/DAO in a Spring Boot project harmful?
问题
我刚开始学习Spring,之前主要是从事Java EE开发,所以像IOC和依赖注入这样的东西对我来说都是比较新的。根据Spring文档的说明,我理解任何一个类要调用其依赖项的实例,我可以选择将这些依赖项自动连接,作为一种依赖项注入的形式。实际上,这与我们在Java中通常做的常规实例声明是分开的,就像下面这样:Animal animal1 = new Animal()
在我的一个小测试Spring Boot项目服务中,我注意到我最终既要进行依赖项注入,又要进行普通的类实例化。我使用JPA Repository来构建我的存储库层,并自动连接存储库类,以便我可以像这样使用它们:
@Autowired
customerAccountRepo
这一切都很好。我还有一个DAO customerMembershipValidity
,其属性是其他声明的POJO,并且其中有一些公共辅助函数来设置DAO的属性。然而,为了使用这个DAO,我发现自己需要以传统的方式创建DAO的多个实例,通过多次实例化CustomerMembershipValidity customerMembershipValidity1 = new CustomerMembershipValidity()
来在服务中调用公共的辅助方法,比如customerMembershipValidity.setNewExpiry()
。我认为不需要自动连接这个,因为我处理的是一个DAO或者POJO,而不是另一个服务...或者应该连接吗?
目前看来,当我进行单元测试时,代码似乎是功能正常的,但我想知道这是否会损害代码的整体持久性和合理性,或者在我运行Spring Boot应用程序时是否有可能在端到端测试中出现问题。
英文:
I'm just starting to pick up Spring, coming from a purely Java EE background, so stuff like IOC and dependency injection is all kinda new to me. As per the Spring docs, I understand that for any class to call on instances of its dependencies, I can choose to autowire those dependencies as a form of dependency injection. And that this is actually aside from the usual instance declaration we always do in java like below: Animal animal1 = new Animal()
In my one of my little test Spring boot project services, I noticed that I end up doing both dependency injection and normal class instantiation. I use JPA Repository to craft my repo layer, and autowire the repo classes so I can use them like eg.
@Autowired
customerAccountRepo
This is all fine. I also have a DAO customerMembershipValidity
whose attributes are other declared POJOs and has some public helper functions within to set the DAO's attributes. In order to use this DAO, however, I find myself creating multiple instances of the DAO the traditional way, instantiating
CustomerMembershipValidity customerMembershipValidity1 = new CustomerMembershipValidity()
multiple times throughout the service to call on public helper methods like customerMembershipValidity.setNewExpiry()
. I didnt think there would be a need to autowire this since I'm dealing with a DAO or POJO, not another service... or should I?
For now, the code seems functional when I do my unit-testing, but I would like to know if this would harm the overall longevity and sensibility of the code, or if it's forseeable to end up breaking in E2E when I run the Spring Boot application.
答案1
得分: 0
我有一些建议:
- DAO 应该是一个单例的 Spring Bean,你将其注入到需要它的服务 Bean 中。确保在 DAO 中没有可变的共享状态,只有数据库操作。
- 我编写的 DAO 可能会使用映射函数将 ResultSet 映射到对象/集合,但我不认为需要使用辅助函数。
- Spring 偏好使用构造函数注入。你不应该使用 setter 或 autowired 属性来注入依赖。
- 如果你使用 new,意味着该对象不受 Spring 控制。在方法范围内为对象调用 new 是适当的,但不适用于像 DAO 这样的 Spring Bean。
- 单元测试和生产环境是两回事。我倾向于在单元测试中不使用 Spring。我在 JUnit 测试中调用 new,但不在生产代码中使用。一旦我测试过 DAO,就可以为依赖于它的服务使用模拟。
你明智地选择了学习 Spring,将 Java EE 抛在身后。Java EE 已经是一个二十年前的过时标准。
英文:
I have a few recommendations:
- DAO should be a singleton Spring Bean that you inject into service bean(s) that need it. Make sure there is no mutable shared state in your DAO - just database operations.
- The DAOs I write might use mapper functions to map ResultSet to objects/collections, but I don't see the need for helpers.
- Spring preference is to use constructor injection. You should not use setter or autowired attribute to inject dependencies.
- If you use new, that means the object is not under Spring's control. It's appropriate to call new for objects in method scope, but not a Spring Bean like a DAO.
- Unit testing and production are two different things. I prefer to leave Spring out of unit testing. I call new for JUnit tests, but not production code. Once I've tested the DAO, I can use mocks for services that depend on it.
You're smart to take up Spring and leave Java EE behind. It's a twenty year old dead standard.
专注分享java语言的经验与见解,让所有开发者获益!
评论