Spring 具有运行时构造函数参数的 bean
Spring bean with runtime constructor arguments
我想在 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
您的代码看起来不错,要使用 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)给了你错误,它不是 runtime/compile 时间错误。
在 IntelliJ 中,您可以更改 Spring 检查的设置。
- 转到文件 -> 设置。
- 在搜索框中键入检查。
- 转到 Spring Core->Code->Bean 的自动装配 类。
- 从"Error"改为“弱警告”
您可以将原型 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;
}
这可以通过在 Spring 4.3 中引入的 Spring 的 ObjectProvider<>
class 来实现。有关详细信息,请参阅 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工厂方法。
我想在 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
您的代码看起来不错,要使用 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)给了你错误,它不是 runtime/compile 时间错误。
在 IntelliJ 中,您可以更改 Spring 检查的设置。
- 转到文件 -> 设置。
- 在搜索框中键入检查。
- 转到 Spring Core->Code->Bean 的自动装配 类。
- 从"Error"改为“弱警告”
您可以将原型 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;
}
这可以通过在 Spring 4.3 中引入的 Spring 的 ObjectProvider<>
class 来实现。有关详细信息,请参阅 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工厂方法。