Как точно работать с конфигурацией прокси на основе Spring Inheritance?

Я готовлюсь к сертификации 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, возвращает этот компонент, в противном случае вызывает тот же метод в супер класс, создающий новый компонент и помещающий его в контекст приложения

Это правильное значение наследования на основе шаблона прокси или я что-то упустил?


person AndreaNobili    schedule 14.11.2014    source источник
comment
+1 Несомненно, очень интересный вопрос.   -  person Paul Vargas    schedule 14.11.2014
comment
Сертификация Spring Core привела меня сюда   -  person Akhil Jain    schedule 17.06.2015


Ответы (1)


Да, то, что вы описали, в основном соответствует тому, как -java-config" rel="nofollow">Spring обрабатывает @Configuration классы

Все классы @Configuration подклассифицируются во время запуска с помощью CGLIB. В подклассе дочерний метод сначала проверяет контейнер на наличие кэшированных (с заданной областью действия) bean-компонентов, а затем вызывает родительский метод и создает новый экземпляр.

Если проблема в вопросе сертификации состоит в том, чтобы иметь только один экземпляр new JdbcAccountRepository(), тогда да, лучше всего использовать метод accountRepository() @Bean в классе @Configuration.

person Sotirios Delimanolis    schedule 14.11.2014