2015-03-16 8 views
6

Sto studiando per la certificazione Spring Core e ho alcuni dubbi relativi alla risposta a questa domanda fondata sul materiale di studio.Perché in primavera non sono autorizzato ad annotare una classe finale con @Configuration?

Perché non ammessi per annotare una classe finale con @Configuration

Il mio ragionamento è la seguente per suffragare questa affermazione:

Si consideri il seguente classe di configurazione:

A prima vista questa situazione potrebbe sembrare strana perché il primo metodo (accountRepository()) istanzia un oggetto JdbcAccountRepository come fagiolo avente id = AccountRepository che, seguendo il comportamento predefinito Spring, è un singoletto

Il secondo e il terzo metodo di chiamata due volte più tempo il accountRepository() metodo che dovrebbe creare un'istanza di altri due oggetti JdbcAccountRepository e questo non è possibile perché è singleton !!!

Così, per risolvere questa situazione Primavera utilizzare i Proxy eredità a base strategia che si aspettano di creare una classe figlia della mia classe di configurazione (quella annotata da @Configuration) ed è fa:

  • Per ogni chicco, un'istanza viene memorizzato nella cache nella classe figlia

  • C Classe Hild solo chiamate super-a prima esemplificazione

Così la classe bambino è il punto di ingresso perché il seguente comportamento viene implementato da questa classe bambino:

public class AppConfig $$ EnhancerByCGLIB $ estende AppConfig {

public AccountRepository accountRepository() { 
    // if bean is in the applicationContext 
    // return bean 
    // else call super.accountRepository() and store bean in context 
} 

public TransferService transferService() { 
    // if bean is in the applicationContext, return bean 
    // else call super.transferService() and store bean in context 
} 

..................................................... 
..................................................... 
..................................................... 
} 

Quindi, se ho annotare una classe di configurazione con finale Primavera non può avere questo comportamento perché in Java una classe finale non può essere sottoclasse

E 'corretto?

Utilizzando lo stesso ragionamento posso anche affermare che in primavera non riesco ad annotare un metodo finale con l'annotazione @Bean?

Perché, come mostrato nell'esempio precedente, non ho che quando al tempo di avvio viene creata la classe figlia (il proxy) della mia classe di configurazione capita che per ciascun bean, un'istanza viene memorizzato nella cache nella classe figlia e se è definitivo non è possibile (ma non sono assolutamente sicuro di questa asserzione)

Mi manca qualcosa? Puoi darmi la spiegazione esatta?

Tnx

risposta

7

primavera crea proxy dinamici per le classi annotate con @Configuration classi. Spring usa CGLIB per estendere la tua classe per creare proxy. Quindi, le classi di configurazione non possono essere definitive.

Per quanto riguarda accountRepository() essere invocato due volte:

Se si richiama accountRepository() metodo per creare un esempio, non è più una primavera gestito fagioli. Spring non avrà alcuna idea delle istanze create in questo modo. Quindi, si finirà con più istanze di JdbcAccountRepository

È possibile mantenere il comportamento Singleton se si configura come di seguito:

@Bean 
public TransferService transferService(JdbcAccountRepository jdbcAcctRepo) { 
    TransferServiceImpl service = new TransferServiceImpl(); 
    service.setAccountRepository(jdbcAcctRepo); 
    return service; 
} 

@Bean 
public AccountService accountService(JdbcAccountRepository jdbcAcctRepo) { 
    return new AccountServiceImpl(jdbcAcctRepo); 
} 
+2

In realtà se la sottoclasse funziona correttamente, è possibile chiamare altri metodi di fagioli (come accountRepository ()). Il proxy determinerà quindi se è necessario creare una nuova istanza di bean o se ne esiste già una. – dunni

+0

Se la classe di configurazione non è definitiva, Spring può sottoclasse. E, in relazione al richiamo del metodo 'accountRepository()', Spring non sa cosa sta accadendo all'interno del metodo. Spring non può collegarsi in una logica per verificare se il bean è già stato creato, ogni volta che viene utilizzato l'operatore 'new'. – Mithun

+1

Anche se è un po 'tardi, ma sono inciampato di nuovo su questa risposta: Ovviamente Spring non può vedere cosa succede nel metodo accountRepository(). Ma il proxy Spring intercetterà tutte le chiamate al metodo accountRepository() stesso e controlla se c'è già un bean di quel tipo e nome definito nel contesto dell'applicazione corrente. Se questo è il caso, il proxy restituisce il bean (e non esegue il metodo), in caso contrario, viene chiamato il metodo reale e il bean restituito viene archiviato nel contesto dell'applicazione. Ecco perché è sicuro chiamare i metodi di creazione dei bean più volte in un bean di configurazione – dunni

Problemi correlati