Java 带有运行时构造函数参数的 Spring bean
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35108778/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring bean with runtime constructor arguments
提问by suraj bahl
I want to create a Spring bean in Spring Java configurationwith some constructor arguments passed at runtime. I have created the following Java config, in which there is a bean fixedLengthReportthat expects some arguments in constructor.
我想在Spring Java 配置中创建一个 Spring bean,并在运行时传递一些构造函数参数。我创建了以下 Java 配置,其中有一个 bean fixedLengthReport需要构造函数中的一些参数。
@Configuration
public class AppConfig {
@Autowrire
Dao dao;
@Bean
@Scope(value = "prototype")
**//SourceSystem can change at runtime**
public FixedLengthReport fixedLengthReport(String sourceSystem) {
return new TdctFixedLengthReport(sourceSystem, dao);
}
}
But i am getting error that sourceSystemcouldn't wire because no bean found. How can I create bean with runtime constructor arguments?
但是我收到错误消息,因为找不到 bean ,sourceSystem无法连接。如何使用运行时构造函数参数创建 bean?
I am using Spring 4.2
我正在使用 Spring 4.2
采纳答案by Ken Bekov
You can use a prototype bean along with a BeanFactory
.
您可以将原型 bean 与BeanFactory
.
@Configuration
public class AppConfig {
@Autowired
Dao dao;
@Bean
@Scope(value = "prototype")
public FixedLengthReport fixedLengthReport(String sourceSystem) {
return new TdctFixedLengthReport(sourceSystem, dao);
}
}
@Scope(value = "prototype")
means that Spring will not instantiate the bean right on start, but will do it later on demand. Now, to customize an instance of the prototype bean, you have to do the following.
@Scope(value = "prototype")
意味着 Spring 不会在开始时实例化 bean,而是会在稍后按需实例化。现在,要自定义原型 bean 的实例,您必须执行以下操作。
@Controller
public class ExampleController{
@Autowired
private BeanFactory beanFactory;
@RequestMapping("/")
public String exampleMethod(){
TdctFixedLengthReport report =
beanFactory.getBean(TdctFixedLengthReport.class, "sourceSystem");
}
}
Note, because your bean cannot be instantiated on start, you must not Autowire your bean directly; otherwise Spring will try to instantiate the bean itself. This usage will cause an error.
注意,因为你的 bean 不能在启动时实例化,你不能直接自动装配你的 bean;否则 Spring 将尝试实例化 bean 本身。这种用法会导致错误。
@Controller
public class ExampleController{
//next declaration will cause ERROR
@Autowired
private TdctFixedLengthReport report;
}
回答by Haim Raman
You code looks fine, to get the prototype with parameters use the BeanFactory#getBean(String name, Object... args) method.
您的代码看起来不错,要使用 BeanFactory#getBean(String name, Object... args) 方法获取带参数的原型。
Look at Spring Java Config: how do you create a prototype-scoped @Bean with runtime arguments?BeanFactory#getBean(String name, Object... args) would be what you are looking for.
看一下Spring Java Config:如何使用运行时参数创建原型范围的 @Bean?BeanFactory#getBean(String name, Object... args) 就是你要找的。
I guess that your IDEA (in my case IntelliJ IDEA version 15.) give you the error and it's not a runtime/compile time error.
我猜您的 IDEA(在我的情况下是 IntelliJ IDEA 版本 15。)给了您错误,这不是运行时/编译时错误。
In IntelliJ you can change the setting of Spring inspections.
在 IntelliJ 中,您可以更改 Spring 检查的设置。
- Go to file -> settings.
- Type inspections in the search box.
- Go to Spring Core->Code->Autowire for Bean Classes.
- Change from "Error" to “weak warning”
- 转到文件-> 设置。
- 在搜索框中键入检查。
- 转到 Spring Core->Code->Autowire for Bean Classes。
- 从“错误”变为“弱警告”
回答by HairOfTheDog
This can be achieved with Spring's ObjectProvider<>
class which was introduced in Spring 4.3. See Spring's documentationfor additional details.
这可以通过ObjectProvider<>
Spring 4.3 中引入的 Spring 类来实现。有关其他详细信息,请参阅 Spring 的文档。
The gist is to define the bean factory method for the object to be provided, inject the ObjectProvider<>
in your consumer and create new instances of the object to be provided.
要点是为要提供的对象定义 bean 工厂方法,将 注入ObjectProvider<>
您的使用者并创建要提供的对象的新实例。
public class Pair
{
private String left;
private String right;
public Pair(String left, String right)
{
this.left = left;
this.right = right;
}
public String getLeft()
{
return left;
}
public String getRight()
{
return right;
}
}
@Configuration
public class MyConfig
{
@Bean
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public Pair pair(String left, String right)
{
return new Pair(left, right);
}
}
@Component
public class MyConsumer
{
private ObjectProvider<Pair> pairProvider;
@Autowired
public MyConsumer(ObjectProvider<Pair> pairProvider)
{
this.pairProvider = pairProvider;
}
public void doSomethingWithPairs()
{
Pair pairOne = pairProvider.getObject("a", "b");
Pair pairTwo = pairProvider.getObject("z", "x");
}
}
NOTE: you don't actually implement the ObjectProvider<>
interface; Spring does that for you automagically. You just need to define the bean factory method.
注意:您实际上并未实现该ObjectProvider<>
接口;Spring 会自动为您执行此操作。您只需要定义 bean 工厂方法。