@Autowired 注解在 Spring 中如何工作?
真正的问题是为什么我可以用以下两种方式编写此代码:
@Controller
public class PostController {
@Autowired
private PostService postService;
@Autowired
private CommentService commentService;
....
}
以及
@Controller
public class PostController {
private PostService postService;
private CommentService commentService;
@Autowired
public PostController(PostService postService, CommentService commentService){
this.postService = postService;
this.commentService = commentService;
}
....
}
这些片段是否相同?推荐哪一款?
The real question is why am I allowed to write this code in the following two ways :
@Controller
public class PostController {
@Autowired
private PostService postService;
@Autowired
private CommentService commentService;
....
}
and
@Controller
public class PostController {
private PostService postService;
private CommentService commentService;
@Autowired
public PostController(PostService postService, CommentService commentService){
this.postService = postService;
this.commentService = commentService;
}
....
}
Are these snippets identical? Which one is recommended?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
第一个解决方案直接通过反射注入值(基本上 JVM 会获取您的对象并手动设置值)。
第二种解决方案使用构造函数,这意味着参数是强制性的。另外,在将其分配给您的属性之前,您有时间使用该值。 (注意构造函数也会被反射调用)。
另一种方法是使用 setter,这次调用一个方法来设置值,以便您可以在实际设置之前使用它,但这不是强制性的(因为它不是构造函数的一部分)。
关于推荐的,我不确定是否真的有一个“官方推荐”,但我倾向于只对强制字段使用构造函数注入,对非强制字段使用setter注入。但据我所知,这主要取决于与您合作的团队或您的品味。
The first solution directly injects values with reflection (basically the JVM will take your object and manually set the value).
The second solution uses a constructor, that means the parameter is mandatory. Plus you have time to play with the said value before assigning it yourself to your attribute. (note that the constructor will also be called by reflection).
Another way is to use a setter, this time a method is called to set the value so you can play with it before actually setting it, but it's not mandatory (as it's not a part of the constructor).
Regarding the recommended one, I'm not sure there is actually one "officially recommended", but I tend to only use Constructor injection for mandatory fields and setter injection for non mandatory fields. But as far as I know it mostly depends on the team your working with or your taste.
您可以用两种不同的方式编写它们,因为 Spring 已决定支持这两种方式从其应用程序上下文注入 bean(甚至还有第三种!)。
他们大部分时间都会做同样的事情。但每个人的工作方式都有细微的差别。请查看 文档以供进一步说明,因为可以在那里更好地解释详细信息。
You can write them in two different ways because Spring has decided to support those two ways to inject beans from its application context (there is even a third!).
They will do the same thing most of the time. But each has subtle differences in how they work. Please take a look at the documentation for further clarification, as the minute details can be explained better there.
我希望在 PostController 中的构造函数返回后注入第一个示例中的依赖项。在第二个示例中,我希望在构造函数执行时注入依赖项。即第二个示例可以保证在构造函数执行时存在依赖关系,而第一个示例则不会。
I would expect the dependencies in the first example to be injected after the constructor in the PostController has returned. In the second example I would expect the dependencies to be inject as the constructor executes. i.e. the second example would sort of guarantee that the dependencies are there as the constructor executes which the first example would not.
从测试的角度来看,它们并不相同。
除非您有 PostService 和 CommentService 的 setter 方法,否则您无法轻松设置它们的值。
通常对于像这样的@Autowired,它设置为包范围
相反,
我们确实
注意到没有“私人”。
这样做的原因是...
只有具有相同包的类才能读取/写入变量,并且当您执行测试类时,通常它与被测试的单元位于同一包下。
From a testing point of view, they are NOT the same.
Unless you have a setter method for PostService and CommentService, you can't easily set their values.
Usually for @Autowired like that, its set as package scope
instead of
we do
Notice no "private".
Reason to do this is...
Only classes with the same package can read/write the variable and when you do your test class, usually its under the same package as the unit under test.