Spring

时间:2018-02-20 11:12:56

标签: java spring spring-boot

我在我的应用程序中使用SpringBoot,目前正在使用applicationContext.getBean(beanName,beanClass)来获取我的bean,然后再对其执行操作。我在几个问题中看到,不鼓励使用getBean()。由于我对春天很新,所以我不了解所有最佳实践并且存在冲突。上述链接问题中提出的解决方案可能在我的用例中不起作用。我该怎么做呢?

@RestController
@RequestMapping("/api")
public class APIHandler {
    @Value("${fromConfig}")
    String fromConfig;

    private ApplicationContext applicationContext;

    public Bot(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @PostMapping(value = "")
    public ResponseEntity post(@RequestBody HandlingClass requestBody) {
        SomeInterface someInterface = applicationContext.getBean(fromConfig, SomeInterface.class);
        someInterface.doSomething();
    }
}

我有一个名为SomeInterface的接口,定义如下:

public interface SomeInterface {

    void doSomething();
}

我有2个类实现了这个名为UseClass1UseClass2的接口。我的配置文件存储一个字符串,其中包含我在运行时需要知道的类的bean名称,并调用该方法的相应实现。

任何指示都将不胜感激。

5 个答案:

答案 0 :(得分:2)

您可以使用

定义spring bean组件
  

05b6c0eeceee49c759d/BeautifulSoup- 3.2.1.tar.gz#md5=44656527ef3ac9874ac4d1c9f35f70ee Best match: BeautifulSoup 3.2.1 Processing BeautifulSoup-3.2.1.tar.gz Writing C:\Users\Owner\AppData\Local\Temp\easy_install- iwb6x4a5\BeautifulSoup-3.2.1\setup.cfg Running BeautifulSoup-3.2.1\setup.py -q bdist_egg --dist-dir C:\Users\Owner\AppData\Local\Temp\easy_install-iwb6x4a5\BeautifulSoup- 3.2.1\egg-dist-tmp-rtwdsovx Traceback (most recent call last): File "d:\python3_64\lib\site-packages\setuptools\sandbox.py", line 154, in save_modules yield saved File "d:\python3_64\lib\site-packages\setuptools\sandbox.py", line 195, in setup_context yield File "d:\python3_64\lib\site-packages\setuptools\sandbox.py", line 250, in run_setup _execfile(setup_script, ns) File "d:\python3_64\lib\site-packages\setuptools\sandbox.py", line 44, in _execfile code = compile(script, filename, 'exec') File "C:\Users\Owner\AppData\Local\Temp\easy_install- iwb6x4a5\BeautifulSoup-3.2.1\setup.py", line 22 print "Unit tests have failed!" ^ SyntaxError: Missing parentheses in call to 'print'. Did you mean print(int "Unit tests have failed!")? During handling of the above exception, another exception occurred: Traceback (most recent call last): File "d:\python3_64\lib\runpy.py", line 193, in _run_module_as_main "__main__", mod_spec) File "d:\python3_64\lib\runpy.py", line 85, in _run_code exec(code, run_globals) File "D:\Python3_64\Scripts\easy_install.exe\__main__.py", line 9, in <module> File "d:\python3_64\lib\site-packages\setuptools\command\easy_install.py", line 2312, in main **kw File "d:\python3_64\lib\site-packages\setuptools\__init__.py", line 129, in setup return distutils.core.setup(**attrs) File "d:\python3_64\lib\distutils\core.py", line 148, in setup dist.run_commands() File "d:\python3_64\lib\distutils\dist.py", line 955, in run_commands self.run_command(cmd) File "d:\python3_64\lib\distutils\dist.py", line 974, in run_command cmd_obj.run() File "d:\python3_64\lib\site-packages\setuptools\command\easy_install.py", line 412, in run self.easy_install(spec, not self.no_deps) File "d:\python3_64\lib\site-packages\setuptools\command\easy_install.py", line 673, in easy_install return self.install_item(spec, dist.location, tmpdir, deps) File "d:\python3_64\lib\site-packages\setuptools\command\easy_install.py", line 699, in install_item dists = self.install_eggs(spec, download, tmpdir) File "d:\python3_64\lib\site-packages\setuptools\command\easy_install.py", line 884, in install_eggs @Profile("dev")

@Profile("test")作为提及评论,然后使用

切换配置文件
inject

答案 1 :(得分:2)

这只是代码,我可以从ApplicationContext动态获取bean

@Service
public class AuthenticationService {

    @Autowired
    private ApplicationContext сontext;

    public boolean authenticate(...) { 
        boolean useDb = ...;   //got from db
        IAuthentication auth = context.getBean(useDb ? DbAuthentication.class : LdapAuthentication.class);       
        return auth.authenticate(...);
    }
}

答案 2 :(得分:2)

从Spring 4.3开始,您可以将所有实现自动装配到由BeanName&lt; =&gt;对组成的Map中。 beanInstance:

public class APIHandler {

    @Autowired
    private Map<String, SomeInterface> impls;

    public ResponseEntity post(@RequestBody HandlingClass requestBody) {
        String beanName = "..."; // resolve from your requestBody        
        SomeInterface someInterface = impls.get(beanName);
        someInterface.doSomething();
    }
}

假设您有两个实现,如下面的

// qualifier can be omitted, then it will be "UseClass1" by default
@Service("beanName1") 
public class UseClass1 implements SomeInterface { } 

// qualifier can be omitted, then it will be "UseClass2" by default
@Service("beanName2")
public class UseClass2 implements SomeInterface { } 

答案 3 :(得分:1)

真正的问题不是如何来解决这个问题,但为什么会根据配置值注入不同的东西?

如果答案正在测试,那么最好使用@Profile s作为@murat建议。

为什么在类路径上有不同的接口实现?

您是否无法以一种用例的方式打包您的应用程序? (见ContextConfiguration

答案 4 :(得分:1)

我认为您应该使用配置类根据fromConfig字符串值生成bean:

你的控制器:

@RestController
@RequestMapping("/api")
public class APIHandler {

    @Autowired
    SomeInterface someInterface;

    @PostMapping(value = "")
    public ResponseEntity post(@RequestBody HandlingClass requestBody) {
        someInterface.doSomething();
    }
}

豆类生产者:

@Configuration
public class SomeInterfaceProducer {

    @Value("${fromConfig}")
    String fromConfig;

    @Bean
    public SomeInterface produce() {

        if (fromConfig.equals("aValueForUseClass1") {
            return new UseClass1();
        } else {
            return new UseClass2();
        }
        //...
    }
}

或者如果你在UseClass1和/或UseClass2中有DI:

@Configuration
public class SomeInterfaceProducer {

    @Value("${fromConfig}")
    String fromConfig;

    @Bean
    public SomeInterface produce(@Autowired YourComponent yourComponent) {
        SomeInterface someInterface;
        if (fromConfig.equals("aValueForUseClass1") {
            someInterface = new UseClass1();
            someInterface.setYourComponent(yourComponent);
            // or directly with the constructor if you have one with yourComponent as parameter.
        } else {
            someInterface = new UseClass2();
            someInterface.setYourComponent(yourComponent);
        }
        //...
    }
}