简体   繁体   English

在 spring 中使用 applicationContext.getBean() 创建 bean 时如何指定要使用的组件?

[英]How do I specify which component to use while creating the bean using applicationContext.getBean() in spring?

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.在获取 bean applicationContext.getBean(GameRunner.class)时,我希望能够指定游戏以在GameRunner class 中实例化GamingSoftware变量。

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 .当我运行上面的代码时,它给了我一个错误,比如,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?如何指定在我的applicationContext.getBean()方法中使用哪个组件?

In springboot the context is not loaded while applicationContext.getBean().在 springboot 中,在 applicationContext.getBean() 时不加载上下文。 The context is loaded in SpringApplication.run(GamingDevice.class, args), so in that line is when the exception is throw.上下文在 SpringApplication.run(GamingDevice.class, args) 中加载,因此在该行中是抛出异常的时间。

For runnig you must eliminate the @Autowired on GamingSoftware and load it using a set property:对于 runnig,您必须消除 GamingSoftware 上的 @Autowired 并使用设置属性加载它:

    @Component
    public class GameRunner {
    
        private GamingSoftware game;
        
        public void run() {
            game.up();
            game.down();
            game.left();
            game.right();
        }
    
        public GamingSoftware getGame() {
            return game;
        }
    
        public void setGame(GamingSoftware game) {
            this.game = game;
        }
        
    }

@SpringBootApplication
public class GamingDevice {

    public static void main(String[] args) {
         ConfigurableApplicationContext applicationContext = SpringApplication.run(GamingDevice.class, args);
         GameRunner gameRunner = applicationContext.getBean(GameRunner.class);
         gameRunner.setGame(applicationContext.getBean("superContra",GamingSoftware.class));
         gameRunner.run();
    }

}

The function getBean() supports parameters to supplier bean constructors. function getBean()支持供应商 bean 构造函数的参数。 You can pass the proper GamingSoftware instance when you calling the getBean(Class, Args...)您可以在调用getBean(Class, Args...)时传递正确的 GamingSoftware 实例

Read more about get beans here 在此处阅读有关获取豆子的更多信息

You can create a property in application.properties (or application.yml) for example例如,您可以在application.properties(或 application.yml)中创建一个属性

myapp.gametype=mario

Then add to your @Component annotation @ConditionalOnProperty然后添加到您的@Component 注释@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.下次 Spring 将只创建一个 GamingSoftware 接口的 Bean,这取决于您的属性有什么价值。

Beans are created with a name based on the concrete class name (with first letter made lowercase). Bean 的创建名称基于具体的 class 名称(首字母小写)。 Try尝试

applicationContext.getBean(“superMario”)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM