Я готовлюсь к сертификации Spring Core и обнаруживаю некоторые сомнения, связанные с понятием прокси.
Итак, по учебному материалу я нахожу следующую викторину:
Существует класс конфигурации Java, который содержит следующие методы:
@Bean
public AccountRepository accountRepository(){
return new JdbcAccountRepository();
}
@Bean
public TransferService transferService1() {
TransferServiceImpl service = new TransferServiceImpl();
service.setAccountRepository(accountRepository());
return service;
}
@Bean
public TransferService transferService2() {
return new TransferServiceImpl( new JdbcAccountRepository() );
}
Как видите, существует 2 разные реализации transferService(), соответственно названные transferService1() и transferService2(), которые создают и возвращают Объект TransferServiceImpl.
Первый создает новый объект TransferServiceImpl, а затем вызывает для него метод setAccountRepository().
Второй просто создает TransferServiceImpl, передавая новый объект JdbcAccountRepository в свой конструктор.
Он спрашивает меня ** Какая реализация лучше двух предыдущих методов?
И ответ: Предпочитать вызов выделенного метода. Поэтому я думаю, что это говорит о том, что лучший способ - это первая реализация.
В нем объясняется, что компонент AccountRepository является одиночным (поскольку это стандартная область действия для компонентов в Spring), но JdbcAccountRepository() может быть вызывается два или более раз (например, в предыдущем фрагменте кода он вызывается, когда вызываются методы transferService1() и transferService2(), и если это так, это будет проблемой поскольку AccountRepository должен быть одноэлементным.
Это правда? Или я что-то упускаю?
Итак, я понимаю, что во время запуска для каждого класса конфигурации (с аннотацией @Configuration) создается дочерний класс, который расширяет мой класс конфигурации.
Например, если у меня есть следующий класс конфигурации:
@Configuration
public class AppConfig {
@Bean public AccountRepository accountRepository() { ... }
@Bean public TransferService transferService() { ... }
}
автоматически создается следующий класс, расширяющий мой AppConfig:
public class AppConfig$$EnhancerByCGLIB$ extends AppConfig {
public AccountRepository accountRepository() { // ... }
public TransferService transferService() { // ... }
...
...
...
}
Таким образом, дочерний класс является точкой входа (вызываются методы, определенные в дочернем классе), а псевдокод будет примерно таким:
public class AppConfig$$EnhancerByCGLIB$ extends 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
}
}
Таким образом, кажется довольно ясным, как Spring может справиться с проблемой синглтона: он вызывает методы в прокси-классе, который расширяет класс конфигурации, и если запрошенный компонент существует в applicationContext, возвращает этот компонент, в противном случае вызывает тот же метод в супер класс, создающий новый компонент и помещающий его в контекст приложения
Это правильное значение наследования на основе шаблона прокси или я что-то упустил?