假设您有一个原型bean类,如下所示:
@Component
@Scope("prototype")
public class Foobar {
private String foo;
public Foobar( String foo ) {
this.foo = foo;
}
}
那么,是否可以使用@Autowired
将这样的bean连接到另一个类中,该类应该使用非默认构造函数Foobar(String foo)
来实例化bean?
更新
在上面的示例中,构造函数参数String foo
在应用程序上下文中不可用,而是动态的。因此,使用@Autowired
注释构造函数,然后在上下文中的某处指定foo
似乎不是一个理想的解决方案。
答案 0 :(得分:18)
以下是3种方法,只需查看最适合您情况的方法:
更好:您拥有在上下文中构建原型bean所需的一切(即使是@Value("${prop}")
等属性)
如果你想要一种自动方式,你需要拥有在上下文中实例化bean所需的一切(即使对于原型bean)。如果您在上下文中拥有所需的所有内容,您只需将构造函数注释为@Autowired
,Spring将为您完成剩下的工作。
@Component
@Scope("prototype")
public class FooBar {
private Baz baz;
@Autowired
public FooBar(Baz baz) {
this.baz = baz;
}
}
FactoryBeans
更好:如果您使用的是基于XML的上下文,您会更喜欢这种方式。
如果您需要个性化的方式,另一种可能性是使用FactoryBean
。来自documentation:
由BeanFactory中使用的对象实现的接口,这些对象本身就是工厂。如果bean实现了这个接口,它将被用作公开的对象的工厂,而不是直接作为将自己公开的bean实例。
Spring使用FactoryBean
来构建您请求的对象(原型或单例)。
对于您的情况,您可以使用以下实现:
@Component
public class FooBarFactory implements FactoryBean<FooBar> {
@Autowired
private Baz myContextProvidedObject;
@Override
public FooBar getObject() throws Exception {
return new FooBar(myContextProvidedObject, "my parameter");
}
@Override
public Class<?> getObjectType() {
return FooBar.class;
}
@Override
public boolean isSingleton() {
return false;
}
}
您可以在上下文的其他实例上简单@Autowired
FooBar
。
@Configuration
更好:如果您已经使用注释配置了上下文,那么您肯定会更喜欢这种方式。
第三种方式,这是我的最爱,将使用你的@Configuration
课程。来自documentation:
public @interface Configuration
:表示一个类声明了一个或多个@Bean方法,可能是 由Spring容器处理以生成bean定义和 在运行时为这些bean提供服务请求,例如:
在该课程中,您可以使用以下方法:
@Configuration
public class MyConfig {
@Bean
@Scope("prototype")
public FooBar fooBar(Baz myContextProvidedObject) {
return new FooBar(myContextProvidedObject, "my parameter");
}
}
答案 1 :(得分:3)
您需要使用@Autowired注释构造函数 对于在实例化bean时必须传递给构造函数的参数,必须使用非基本类型参数:
例如:
@Component
@Scope("prototype")
public class FooBar {
private DataSource data;
@Autowired
public FooBar(DataSource data) {
this.bdata = data;
}
}
然后使用以下命令注释您的DataSource:
@Component("dataSupplier")
public class DataSource {
public int getData() {}
}
答案 2 :(得分:1)
由于已启用组件扫描,spring将尝试自动发现并注册另一个Foobar bean。但是这会失败,因为spring无法使用定义的构造函数创建对象,因为您没有在构造函数中自动连接构造函数/参数。作为第二步,spring将尝试使用no-args构造函数创建Foobar。因此,您需要自动连接在spring-config文件中定义的构造函数,以消除此错误。有关此主题的更多信息,请参阅此article。