I have the following classes and interfaces:
public interface GamingSoftware {
public void up();
public void down();
public void left();
public void right();
}
@Component
public class SuperMario implements GamingSoftware {
public void up() { System.out.println("Super Mario: up"); }
public void down() { System.out.println("Super Mario: down"); }
public void left() { System.out.println("Super Mario: left"); }
public void right() { System.out.println("Super Mario: right"); }
}
@Component
public class SuperContra implements GamingSoftware {
public void up() { System.out.println("Super Contra: up"); }
public void down() { System.out.println("Super Contra: down"); }
public void left() { System.out.println("Super Contra: left"); }
public void right() { System.out.println("Super Contra: right"); }
}
@Component
public class GameRunner {
@Autowired
private GamingSoftware game;
public GameRunner(GamingSoftware game) {
this.game = game;
}
public void run() {
game.up();
game.down();
game.left();
game.right();
}
}
@SpringBootApplication
public class GamingDevice {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(GamingDevice.class, args);
GameRunner gameRunner = applicationContext.getBean(GameRunner.class);
gameRunner.run();
}
}
While getting the bean applicationContext.getBean(GameRunner.class)
, I want to be able to specify the game for instantiating the GamingSoftware
variable in the GameRunner
class.
When I run the above code it gives me an error like, Constructor for game runner required a single bean but 2 found SuperMario
and SuperContra
.
How do I specify which component to use in my applicationContext.getBean()
method?
CodePudding user response:
The function getBean()
supports parameters to supplier bean constructors. You can pass the proper GamingSoftware instance when you calling the getBean(Class, Args...)
Read more about get beans here
CodePudding user response:
You can create a property in application.properties (or application.yml) for example
myapp.gametype=mario
Then add to your @Component annotation @ConditionalOnProperty
@Component
@ConditionalOnProperty(name = "myapp.gametype", havingValue = "mario")
public class SuperMario implements GamingSoftware {
public void up() { System.out.println("Super Mario: up"); }
public void down() { System.out.println("Super Mario: down"); }
public void left() { System.out.println("Super Mario: left"); }
public void right() { System.out.println("Super Mario: right"); }
}
@Component
@ConditionalOnProperty(name = "myapp.gametype", havingValue = "contra")
public class SuperContra implements GamingSoftware {
public void up() { System.out.println("Super Contra: up"); }
public void down() { System.out.println("Super Contra: down"); }
public void left() { System.out.println("Super Contra: left"); }
public void right() { System.out.println("Super Contra: right"); }
}
Next time Spring will create only one Bean of GamingSoftware interface depends on what value has your property.
CodePudding user response:
Beans are created with a name based on the concrete class name (with first letter made lowercase). Try
applicationContext.getBean(“superMario”)