选择在运行时弹出时要注入的实现

kwh*_*kwh 6 java spring dependency-injection

我有以下课程:

public interface MyInterface{}

public class MyImpl1 implements MyInterface{}

public class MyImpl2 implements MyInterface{}

public class Runner {
        @Autowired private MyInterface myInterface;
}
Run Code Online (Sandbox Code Playgroud)

我想做的是决定,虽然应用程序已经运行(即不在启动时)应该注入实现Runner.

所以理想情况是这样的:

ApplicationContext appContext = ...
Integer request = ...

Runner runner = null;
if (request == 1) {
        //here the property 'myInterface' of 'Runner' would be injected with MyImpl1
        runner = appContext.getBean(Runner.class) 
}
else if (request == 2) {
        //here the property 'myInterface' of 'Runner' would be injected with MyImpl2
        runner = appContext.getBean(Runner.class)
}
runner.start();
Run Code Online (Sandbox Code Playgroud)

完成此任务的最佳方法是什么?

acc*_*c15 6

@Component("implForRq1")和声明实现@Component("implForRq2")

然后注入它们并使用:

class Runner {

    @Autowired @Qualifier("implForRq1")
    private MyInterface runnerOfRq1;

    @Autowired @Qualifier("implForRq2")
    private MyInterface runnerOfRq2;

    void run(int rq) {
        switch (rq) {
            case 1: runnerOfRq1.run();
            case 2: runnerOfRq2.run();
            ...

        }
    }

}

...

@Autowired
Runner runner;

void run(int rq) {
    runner.run(rq);
}
Run Code Online (Sandbox Code Playgroud)

  • 这是一个糟糕的主意.最好调用某种类型的工厂,它返回所需的实现,而不是散布开关语句.考虑当您需要添加第三个实现时会发生什么 - 您是修改所有代码,还是只修改工厂? (6认同)
  • 实际上,是的,这是一个可怕的想法.任何不包含正确类的创建细节的东西都有一个糟糕的代码味道.如果你没有封装创建代码,猜猜是什么,你将在整个地方创建代码. (2认同)