我想在 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);
}
}
但是我收到的错误是 sourceSystem 无法连接,因为找不到bean。如何使用运行时构造函数参数创建bean?
我使用的是Spring 4.2
答案 0 :(得分:36)
您可以将原型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")
意味着Spring不会在启动时实例化bean,但会在以后按需执行。现在,要自定义原型bean的实例,您必须执行以下操作。
@Controller
public class ExampleController{
@Autowired
private BeanFactory beanFactory;
@RequestMapping("/")
public String exampleMethod(){
TdctFixedLengthReport report =
beanFactory.getBean(TdctFixedLengthReport.class, "sourceSystem");
}
}
注意,因为你的bean在启动时无法实例化,你不能直接自动装配你的bean;否则Spring会尝试实例化bean本身。此用法将导致错误。
@Controller
public class ExampleController{
//next declaration will cause ERROR
@Autowired
private TdctFixedLengthReport report;
}
答案 1 :(得分:2)
你的代码看起来很好,用参数使用BeanFactory#getBean(String name,Object ... args)方法来获取原型。
看看Spring Java Config: how do you create a prototype-scoped @Bean with runtime arguments? BeanFactory#getBean(String name,Object ... args)就是你要找的东西。
我想你的IDEA(在我的情况下是IntelliJ IDEA版本15)会给你错误,而不是运行时/编译时错误。
在IntelliJ中,您可以更改弹簧检查的设置。
答案 2 :(得分:0)
这可以通过Spring 4.3中引入的Spring ObjectProvider<>
类来实现。有关更多详细信息,请参见Spring的documentation。
要点是为要提供的对象定义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");
}
}
注意:您实际上并未实现ObjectProvider<>
接口; Spring会自动为您做到这一点。您只需要定义bean工厂方法。