2015-03-16 8 views
6

Studiuję do certyfikacji Spring Core i mam pewne wątpliwości związane z odpowiedzią na to pytanie oparte na materiałach z badań.Dlaczego wiosną nie wolno mi dodawać adnotacji do ostatniej lekcji z @Configuration?

Dlaczego nie wolno opisywać ostateczną klasę z @Configuration

Moje rozumowanie jest następujące jeden za poparcie tego twierdzenia:

Rozważmy następującą klasę konfiguracji:

@Bean 
public AccountRepository accountRepository() { 
    return new JdbcAccountRepository(); 
} 

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

@Bean 
public AccountService accountService() { 
    return new AccountServiceImpl(accountRepository()); 
} 

Na pierwszy rzut oka ta sytuacja może wydawać się dziwna, ponieważ Pierwszy sposób (accountRepository()) instancję JdbcAccountRepository przedmiot fasoli o id = AccountRepository że po domyślnym Wiosna zachowania jest pojedyncza

Drugie i trzecie połączenie metody razy więcej czasu z accountRepository() metoda, która powinna utworzyć dwa razy więcej JdbcAccountRepository obiektów i to nie jest możliwe, ponieważ jest singleton !!!

Tak więc, aby rozwiązać tę sytuację Wiosna używać proxy dziedziczenie oparte strategia, która się spodziewać utworzyć klasę dzieci z mojej klasy konfiguracji (jeden annoted przez @Configuration) i to robi:

  • Dla każdego ziarna, wystąpienie jest buforowane w klasie dzieci

  • C Klasa Hild tylko nazywa Super w pierwszej instancji

Więc klasa dziecko jest punktem wyjścia, ponieważ następujący zachowanie jest realizowany przez tę klasę dziecko:

public class AppConfig $$ EnhancerByCGLIB $ rozciąga 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 
} 

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

Więc jeśli opisywanie klasę konfiguracji z końcowego sprężyna nie może mieć ten problem, ponieważ w Javie ostateczna klasa nie może być podklasą

Czy to prawda?

Czy mogę z taką samą argumentacją stwierdzić, że wiosną Nie mogę mieć ostatniej metody opatrzonej adnotacją @Bean?

Ponieważ, jak pokazano w poprzednim przykładzie, mam to, że gdy jest tworzony czas uruchomienia, klasa podrzędna (proxy) mojej klasy konfiguracji dzieje się, że dla każdego komponentu bean, instancja jest buforowana w klasie podrzędnej i jeśli jest to ostateczne, nie jest możliwe (ale absolutnie nie jestem pewien co do tego stwierdzenia)

Czy brakuje mi czegoś? Czy możesz podać mi dokładne wyjaśnienie?

Tnx

Odpowiedz

7

Wiosna tworzy dynamiczne proxy dla klas opatrzone @Configuration klas. Spring używa CGLIB do rozszerzenia klasy, aby utworzyć proxy. Dlatego klasy konfiguracji nie mogą być ostateczne.

chodzi accountRepository() powołano dwukrotnie:

Jeśli powołać accountRepository() metodę tworzenia instancji, to nie jest już wiosna udało fasoli. Wiosna nie będzie miała pojęcia o instancjach tworzonych w ten sposób. Stąd też można skończyć z wielu wystąpień JdbcAccountRepository

można zachować singleton zachowanie jeśli skonfigurować jak poniżej:

@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

Właściwie jeśli subclassing działa poprawnie, można wywołać inne metody Bean (jak accountRepository ()). Proxy określi następnie, czy konieczne jest utworzenie nowej instancji komponentu bean, czy też już istnieje. – dunni

+0

Jeśli klasa konfiguracji nie jest ostateczna, Spring może być podklasą. I, związane z inwokacją metody 'accountRepository()', Spring nie wie, co dzieje się wewnątrz metody. Spring nie może przechwycić logiki, aby sprawdzić, czy komponent bean jest już utworzony, za każdym razem, gdy używany jest operator 'new'. – Mithun

+1

Nawet trochę późno, ale po prostu natknąłem się na tę odpowiedź: Oczywiście Spring nie widzi, co dzieje się w metodzie accountRepository(). Ale proxy Spring przechwyci wszystkie wywołania samej metody accountRepository() i sprawdzi, czy istnieje już komponent bean tego typu i nazwy zdefiniowany w bieżącym kontekście aplikacji. W takim przypadku proxy zwraca komponent bean (i nie wykonuje tej metody), jeśli nie, wywoływana jest prawdziwa metoda, a zwracany komponent bean jest przechowywany w kontekście aplikacji. Dlatego bezpieczne jest wielokrotne wywoływanie metod tworzenia komponentu bean w komponencie bean konfiguracji – dunni

Powiązane problemy