2017-10-04 1 views
2

Ich muss mehrere Instanzen einer Spring Bean erstellen (nennen wir es MainPrototypeBean), die ich mit dem prototype Bereich tun kann. Es hängt von einigen anderen Beans ab, und ich möchte jedes Mal, wenn die Haupt-Bean erstellt wird, neue Instanzen von ihnen erstellen. Es gibt jedoch eine gemeinsame Abhängigkeit zwischen einigen der Beans, nennen wir es SharedPrototypeBean. Wie injiziere ich die gleiche Instanz SharedPrototypeBean in jede abhängige Beans, während auch eine neue Instanz für jede MainPrototypeBean?Shared Prototyp Bohnen im Frühjahr

Ich bin in die Implementierung eines benutzerdefinierten Bereichs, aber ich hoffe, einen saubereren Weg zu finden. Es ist keine Option, irgendwelche der Bohnen-Singletons herzustellen, da sie zwischen verschiedenen Instanzen von MainPrototypeBean isoliert werden müssen.

Hier ist ein Beispiel dafür, was ich zu tun habe versucht:

@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; 
    } 
} 

Und die Ausgabe der Ausführung ist:

FirstPrototypeBean.init() with shared [email protected] 
SecondPrototypeBean.init() with shared [email protected] 
+0

Prototyp Bohnen haben unterschiedliche Instanzen für jede Injektion, die der Behälter herstellt. Ich würde argumentieren, dass 'SharedPrototypeBean 'tatsächlich keine prototypische Bean ist, sondern ein' @Scope (" singleton ")'. –

+0

@ M.Prokhorov aber würde das nicht dasselbe bedeuten 'SharedPrototypeBean' würde für alle 'MainPrototypeBean'-Instanzen verwendet werden, was die Anforderung entschärft? – Mena

+0

Hinweis: Ich vermute, dass die Verwendung eines Bereichs-Proxys hier helfen könnte. – Mena

Antwort

0

Nach dem Lesen der Kommentare und der anderen Antwort, erkannte ich, dass das Design tatsächlich zu komplex ist. Ich machte SharedPrototypeBean, FirstPrototypeBean und SecondPrototypeBean regelmäßige POJOs, nicht von Spring verwaltet. Ich erstelle dann alle Objekte in einer mit Annotationen versehenen Methode @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

Sie die FactoryBean für komplexe Konstruktionslogik verwenden können. Implementieren Sie die abstrakte Unterklasse AbstractFactoryBean zum Erstellen eines MainPrototypeBean, und injizieren Sie alle drei abhängigen Beans. Sie können sie dann in der createInstance-Methode miteinander verbinden.

Die FactoryBean Umsetzung:

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; 
} 
} 

Hinweis: sharedPrototype wird nach der Post-Konstrukt Phase im Lebenszyklus des ersten und die zweiten Prototyps injiziert. Wenn Sie in diesen Beans, die sharedPrototype erfordern, eine Logik nach der Konstruktion haben, müssen Sie die init-Methode beim Erstellen der MainPrototypeBean manuell aufrufen.

Ihre Annotation - Konfiguration ändert sich als Konsequenz. Die Attribute sharedPrototype werden nicht mehr autowired (sie sind innerhalb von FactoryBean gesetzt) ​​und MainPrototypeBean ist nicht mehr mit Anmerkungen versehen. Stattdessen müssen Sie die MainFactoryBean erstellen.

@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); 
    } 
} 
} 
Verwandte Themen