2014-12-23 9 views
13

Ho una dipendenza circolare e java config. Mentre risolverlo con xml config è molto semplice non riesco a risolverlo con java config senza @Autowired. Fagioli:Primavera. Risolvi la dipendenza circolare con java config e senza @Autowired

public class A { 
    private B b; 

    public B getB() { 
     return b; 
    } 

    public void setB(B b) { 
     this.b = b; 
    } 
} 

public class B { 
    private A a; 

    public A getA() { 
     return a; 
    } 

    public void setA(A a) { 
     this.a = a; 
    } 
} 

Ho provato questo (ho letto che con @Bean Primavera annotazione non richiamare il metodo si fa riferimento ogni chicco volta, ma in questo caso in realtà è stata invocata per tutto il tempo):

@Configuration 
public class Config { 
    @Bean 
    public A a() { 
     A a = new A(); 
     a.setB(b()); 
     return a; 
    } 

    @Bean 
    public B b() { 
     B b = new B(); 
     b.setA(a()); 
     return b; 
    } 
} 

E questo, con @Autowired di campi classe di configurazione:

@Configuration 
public class Config { 
    @Autowired 
    A a; 
    @Autowired 
    B b; 

    @Bean 
    public A a() { 
     A a = new A(); 
     a.setB(b); 
     return a; 
    } 

    @Bean 
    public B b() { 
     B b = new B(); 
     b.setA(a); 
     return b; 
    } 
} 

Inoltre ho provato tutti di cui sopra con @Lazy annotazione. Non aiuta Ma funziona perfettamente se annoto i setter di A e B con @Autowired. Ma non è quello che voglio adesso. Cosa sto facendo male e c'è un modo per risolvere la dipendenza circolare in java config senza l'uso di @Autowired?

+0

Puoi spiegare _Ma non è quello che voglio adesso._? Se è lo strumento giusto per il lavoro ... –

+0

@Sotirios Delimanolis la mia app è poco confusa al momento e ho paura di confondermi con le dipendenze attorno al codice. Non è religioso e adoro Autowired, ma al momento preferirei concentrare i fagioli in un unico file di configurazione e gestire le dipendenze a mano. Inoltre mi chiedo se è possibile a tutti. –

+0

C'è stata un'interessante discussione sul forum di primavera: http: //forum.spring.io/forum/spring-projects/container/127799-circular-dependencies-con-autowired-in-java-configuration-configuration –

risposta

9

Il comportamento che si desidera ottenere è la seguente

A a = new A(); 
B b = new B(); 
a.setB(b); 
b.setA(a); 

@Bean metodi non vi danno che. Corrono fino al completamento per fornire un'istanza di bean.

Fondamentalmente devi creare parzialmente una delle istanze, quindi terminare l'inizializzazione quando hai creato l'altra.

@Configuration 
class Config { 
    @Bean 
    public A a() { 
     A a = new A(); 
     return a; 
    } 

    @Bean 
    public B b() { 
     B b = new B(); 
     A a = a(); 
     b.setA(a); 
     a.setB(b); 
     return b; 
    } 
} 

o

@Bean 
public B b(A a) { 
    B b = new B(); 
    b.setA(a); 
    a.setB(b); 
    return b; 
} 
+0

Il metodo 'b' potrebbe anche' @ Autowire' bean 'a' (per evitare una chiamata implicita al metodo 'a()'. Non è giusto? – wassgren

+0

@wassgren Assolutamente. Anche se non ha bisogno di esplicito '@ Autowired'. –

+0

Ma questo significa che a e b ottengono riferimenti non decorati l'uno con l'altro. lavoro – flup

6

Un altro approccio utilizzando @Autowired e @Component è quello di utilizzare questo schema:

@Component 
class A { 
    private B b; 

    public B getB() { 
     return b; 
    } 

    public void setB(final B b) { 
     this.b = b; 
    } 
} 


@Component 
class B { 
    private final A a; 

    @Autowired 
    public B(final A a) { 
     this.a = a; 
     a.setB(this); 
    } 

    public A getA() { 
     return a; 
    } 
} 

Questo elimina la necessità di un @Configuration di classe a parte. Inoltre, il metodo setB può essere protetto dal pacchetto se le classi esistono nello stesso pacchetto per ridurre al minimo l'ambito il più possibile.

+0

La tua risposta è anche utile, è triste non posso votare perché sono novizio Grazie –

1

Desidero aggiungere un'altra possibile soluzione per il codice. Invece di impostare le dipendenze circolari nel config:

@Configuration 
public class Config { 
    @Bean 
    public A a() { 
     A a = new A(); 
     a.setB(b()); 
     return a; 
    } 

    @Bean 
    public B b() { 
     B b = new B(); 
     b.setA(a()); 
     return b; 
    } 
} 

si potrebbe anche lasciare che la molla fare il lavoro con la potenza di @Autowired annotazione.

@Configuration 
public class Config { 
    @Bean 
    public A a() { 
     A a = new A(); 
     return a; 
    } 

    @Bean 
    public B b() { 
     B b = new B(); 
     return b; 
    } 
} 

public class A { 
    private B b; 

    @Autowired 
    public setB(B b) { this.b = b; } 
} 

public class B { 
    private A a; 

    @Autowired 
    public setA(A a) { this.a = a; } 
} 

Naturalmente è non banale dal punto "pulito/leggibile/comprensibile" di vista, perché ora la configurazione è mescolato in @Configuration e classe stessa. Ma dato che le dipendenze circolari sono piuttosto rare, potremmo permetterci l'hack.

+0

Il punto era di farlo ** senza ** '@ Autowired' (anche se non chiedermi il motivo per cui –

+0

Oh, capisco, in ogni caso, lascia che sia qui. Grazie. –

Problemi correlati