2017-10-04 69 views
2

我需要创建一个spring bean的多个实例(我们称之为MainPrototypeBean),我可以使用prototype作用域。它依赖于其他一些bean,并且我想在每次创建主bean时创建它们的新实例。但是,一些bean之间存在共享依赖关系,我们称之为SharedPrototypeBean。如何在每个依赖bean中注入相同的SharedPrototypeBean实例,同时为每个MainPrototypeBean创建一个新实例?在春天共享原型豆

我正在考虑实现一个自定义范围,但我希望找到一个更清洁的方式。制作任何bean singletons不是一种选择,因为它们需要在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 [email protected] 
SecondPrototypeBean.init() with shared [email protected] 
+0

原型bean对容器制作的每次注入都有不同的实例。我认为'SharedPrototypeBean'实际上不是原型范围的bean,而是'@Scope(“singleton”)'。 –

+0

@ M.Prokhorov,但是这并不意味着所有的'MainPrototypeBean'实例都会使用相同的'SharedPrototypeBean',因此玷污了必要条件? – Mena

+0

注意:我怀疑使用范围代理可能有帮助。 – Mena

回答

0

在阅读了评论和其他答案之后,我意识到设计确实太复杂。我制作了SharedPrototypeBean,FirstPrototypeBeanSecondPrototypeBean常规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); 
} 
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在第一和第二原型的生命周期中的构建体后阶段之后注入。因此,如果您在这些bean中具有需要sharedPrototype的构建后逻辑,则需要在创建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); 
    } 
} 
}