我在我的应用程序中使用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个类实现了这个名为UseClass1
和UseClass2
的接口。我的配置文件存储一个字符串,其中包含我在运行时需要知道的类的bean名称,并调用该方法的相应实现。
任何指示都将不胜感激。
答案 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);
}
//...
}
}