我需要创建一个spring bean的多个实例(让我们称之为MainPrototypeBean
),我可以使用prototype
范围。它依赖于其他一些bean,我想在每次创建主bean时创建它们的新实例。但是,某些bean之间存在共享依赖关系,我们称之为SharedPrototypeBean
。如何在每个依赖bean中注入相同的SharedPrototypeBean
实例,同时还为每个MainPrototypeBean
创建一个新实例?
我正在考虑实施自定义范围,但我希望找到一种更清洁的方式。制作任何bean单例都不是一种选择,因为它们需要在MainPrototypeBean
的不同实例之间隔离。
以下是我尝试做的一个例子:
@SpringBootApplication
public class DIDemo {
public static void main(String[]args){
ConfigurableApplicationContext context = SpringApplication.run(DIDemo.class, args);
context.getBean(MainPrototypeBean.class);
}
@Component @Scope("prototype") static class SharedPrototypeBean {}
@Component @Scope("prototype") static class FirstPrototypeBean {
@Autowired SharedPrototypeBean shared;
@PostConstruct public void init() {
System.out.println("FirstPrototypeBean.init() with shared " + shared);
}
}
@Component @Scope("prototype") static class SecondPrototypeBean {
@Autowired SharedPrototypeBean shared;
@PostConstruct public void init() {
System.out.println("SecondPrototypeBean.init() with shared " + shared);
}
}
@Component @Scope("prototype") static class MainPrototypeBean {
@Autowired FirstPrototypeBean first;
@Autowired SecondPrototypeBean second;
}
}
执行它的输出是:
FirstPrototypeBean.init() with shared DIDemo$SharedPrototypeBean@1b84f475
SecondPrototypeBean.init() with shared DIDemo$SharedPrototypeBean@539d019
答案 0 :(得分:1)
您可以将FactoryBean
用于复杂构造逻辑。实现其抽象子类AbstractFactoryBean
以创建MainPrototypeBean
,并将所有三个依赖bean注入其中。然后,您可以使用createInstance
方法将它们连接在一起。
FactoryBean实现:
public class MainFactoryBean extends AbstractFactoryBean<MainPrototypeBean> implements FactoryBean<MainPrototypeBean> {
private FirstPrototypeBean firstPrototype;
private SecondPrototypeBean secondPrototpye;
private SharedPrototypeBean sharedPrototype;
public MainFactoryBean(FirstPrototypeBean firstPrototype, SecondPrototypeBean secondPrototype, SharedPrototypeBean sharedPrototype) {
this.firstPrototype = firstPrototype;
this.secondPrototpye = secondPrototype;
this.sharedPrototype = sharedPrototype;
}
@Override
protected MainPrototypeBean createInstance() throws Exception {
MainPrototypeBean mainPrototype = new MainPrototypeBean();
firstPrototype.setSharedPrototypeBean(sharedPrototype);
secondPrototpye.setSharedPrototypeBean(sharedPrototype);
mainPrototype.first = firstPrototype;
mainPrototype.second = secondPrototpye;
//call post construct methods on first and second prototype beans manually
firstPrototype.init();
secondPrototpye.init();
return mainPrototype;
}
@Override
public Class<?> getObjectType() {
return MainPrototypeBean.class;
}
}
注意:sharedPrototype
是在第一个和第二个原型的生命周期中的后构建阶段之后注入的。因此,如果您在这些需要sharedPrototype
的bean中有构造后逻辑,则需要在创建MainPrototypeBean
时手动调用init方法。
您的注释 - 配置随之发生变化。 sharedPrototype
属性不再自动装配(它们在FactoryBean中设置),并且MainPrototypeBean
不再被注释。相反,您需要创建MainFactoryBean
。
@Configuration
public class JavaConfig {
//method name is the name refers to MainPrototypeBean, not to the factory
@Bean
@Scope("prototype")
public MainFactoryBean mainPrototypeBean(FirstPrototypeBean firstPrototype, SecondPrototypeBean secondPrototype, SharedPrototypeBean sharedPrototype) {
return new MainFactoryBean(firstPrototype, secondPrototype, sharedPrototype);
}
//Annotations are not needed anymore
static class MainPrototypeBean {
FirstPrototypeBean first;
SecondPrototypeBean second;
}
@Component
@Scope("prototype")
static class SharedPrototypeBean {
}
@Component
@Scope("prototype")
static class FirstPrototypeBean {
private SharedPrototypeBean shared;
//no autowiring required
public void setSharedPrototypeBean(SharedPrototypeBean shared) {
this.shared = shared;
}
@PostConstruct
public void init() {//reference to shared will be null in post construction phase
System.out.println("FirstPrototypeBean.init() with shared " + shared);
}
}
@Component
@Scope("prototype")
static class SecondPrototypeBean {
private SharedPrototypeBean shared;
public void setSharedPrototypeBean(SharedPrototypeBean shared) {
this.shared = shared;
}
@PostConstruct
public void init() {
System.out.println("SecondPrototypeBean.init() with shared " + shared);
}
}
}
答案 1 :(得分:0)
在阅读了评论和其他答案后,我意识到设计确实太复杂了。我制作了SharedPrototypeBean
,FirstPrototypeBean
和SecondPrototypeBean
常规POJO,不是由Spring管理的。然后我用@Bean
带注释的方法创建所有对象。
@Bean
public MainPrototypeBean mainPrototypeBean() {
Shared shared = new Shared();
First first = new First(shared);
Second second = new Second(shared);
return new MainPrototypeBean(first, second);
}