Reputation: 7568
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?
Upvotes: 3
Views: 3688
Reputation: 888
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
@Autowired
private PostService postService;
we do
@Autowired
PostService postService;
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.
Upvotes: 0
Reputation: 60
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.
Upvotes: 0
Reputation: 93187
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.
Upvotes: 2
Reputation: 42834
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.
Upvotes: 1