public class Player {
@Autowired gameService
@Getter @Setter String name;
public Player(String name) {
this.name = name
}
public doSomething() {
gameService.something() // gameService is null!
}
}
@Service
class GameService { public void something() {...} }
If I were to do new Player("John").doSomething()
java complains that this.gameService is null. Player class is needed to be instantiated.
Is it possible to make gameService autowire to the service correctly?
CodePudding user response:
If I were to do new Player("John").doSomething()
When you create the java instance by your self, this instance is unknown to Spring framework. So Spring will not enrich it with any dependencies it contains.
For your class to contain dependencies via @Autowired
you have to let spring create this instance. Spring in actuality will create a proxy to the class you provide and not the actual class that you have written. One way to achieve that is to mark your class Player
with @Component
and then you must also retrieve the instance player from Spring framework to correctly contain it's dependencies.
Keep in mind that with default @Comopnent
the Player will become a singleton for spring, which doesn't exactly match to the logical use I see you want to have for this class. Either you want it to be a prototype
or even better I think you have to move the use of gameService
outside of Player
class.
Probably you could have the method something()
in GameService
taking as parameter a Player
and doing the same thing. Then you can autowire everywhere the gameService
which sounds like it should be a singleton.
CodePudding user response:
You can make Player a component which makes autowiring available:
@Component
public class Player {
@Autowired
GameService gameService
Additionally, dependency injection best practices are to use constructor based injection:
@Component
public class Player {
private final GameService gameService;
@Autowired
public Player(GameService gameService){
this.gameService = gameService;
}
CodePudding user response:
Since you want gameService
to be @Autowired
, I believe you want some processing to be done based on Player object on that gameService. If yes, instead of calling gameService.something()
, call gameService.something(player)
.
Here is a possible solution:
@Component
public class Player {
@Autowired GameService gameService;
@Getter
@Setter
String name;
public Player() {
}
public Player(String name) {
this.name = name;
}
public void doSomething(Player player) {
gameService.something(player);
}
}
In caller side however, it should be something like:
@Autowired
Player player;
...
public void callPlayer() {
Player johnPlayer = new Player("John");
player.doSomething(johnPlayer);
}
The reason for doing this is let spring create Player component and have dependency injection and you leverage spring created component.
Hope this will help.