Виклик анотованого методу @Bean у конфігурації Java Spring


100

Мені цікаво, як впорскування пружини обробляє викличні методи з @Beanанотацією. Якщо я ставлю @Beanанотацію до методу і повертаю екземпляр, я розумію, що це говорить весни створити компонент, викликаючи метод і отримуючи повернутий екземпляр. Однак іноді цей боб доводиться використовувати для підключення інших бобових компонентів або налаштування іншого коду. Звичайний спосіб це зробити - викликати @Beanанотований метод, щоб отримати екземпляр. Моє запитання полягає в тому, чому це не призводить до того, що навколо буває кілька випадків квасолі?

Наприклад, див. Код нижче (взято з іншого запитання). entryPoint()Метод з анотацією @Bean, так що я б собі уявити , весна буде створити новий екземпляр в BasicAuthenticationEntryPointякості компонента. Потім ми entryPoint()знову телефонуємо в блоці configure, але, схоже, entryPoint()повертає екземпляр bean і не викликається кілька разів (я спробував ввійти в журнал і отримав лише один запис у журналі). Потенційно ми могли б телефонувати entryPoint()кілька разів в інших частинах конфігурації, і ми завжди отримували б той самий екземпляр. Чи правильно я розумію це? Чи робить весна якесь магічне переписування методів, анотованих @Bean?

@Bean
public BasicAuthenticationEntryPoint entryPoint() {
    BasicAuthenticationEntryPoint basicAuthEntryPoint = new BasicAuthenticationEntryPoint();
    basicAuthEntryPoint.setRealmName("My Realm");
    return basicAuthEntryPoint;
}

@Override
protected void configure(HttpSecurity http) throws Exception {

    http
        .exceptionHandling()
            .authenticationEntryPoint(entryPoint())
            .and()
        .authorizeUrls()
            .anyRequest().authenticated()
            .and()
        .httpBasic();       
}

Відповіді:


133

Так, Весна робить якусь магію . Перевірте Spring Docs :

Тут з’являється магія: Усі @Configurationкласи підкласуються під час запуску за допомогою CGLIB . У підкласі дочірній метод спочатку перевіряє контейнер на наявність будь-яких кешованих (масштабованих) компонентів, перш ніж він викликає батьківський метод і створює новий екземпляр.

Це означає, що виклики @Beanметодів проксі- сервером через CGLIB, і тому повертається кешована версія компонента (нова не створюється).

За замовчуванням область @Beans - це SINGLETON, якщо ви вкажете іншу область, таку як PROTOTYPEвиклик буде передано вихідному методу.

Зверніть увагу, що це не діє для статичних методів . Відповідно до весняних документів:

Виклики статичних @Beanметодів ніколи не перехоплюються контейнером, навіть у межах @Configurationкласів (як описано раніше в цьому розділі), через технічні обмеження: підкласифікація CGLIB може замінити лише нестатичні методи. Як наслідок, прямий виклик іншого @Beanметоду має стандартну семантику Java, в результаті чого незалежний екземпляр повертається безпосередньо із самого заводського методу.


Чи можна замінити боби, створені таким чином? Наприклад, у мене є клас, визначений Spring, який безпосередньо викликає метод створення компонента. Що я хочу, так це те, що використовується не бін, створений цим методом, а той, який я визначаю сам (анотовуючи його за допомогою @Beanі @Primary).
Фонс

4
Але я також пам'ятаю, що проксі (jdk або CGLIB, залежно від того, що) не може працювати в режимі самостійного виклику, так як @Configuration визначає залежність між компонентами? Він використовує саме
самовиклик

3
@Nowhy CGLib allows us to create proxy classes at runtime by creating sub class of specified class using Byte code generation. CGLib proxies are used in the case where Proxy is to be created for those class which does not have any interfaces or have methods which are not declared in the implementing interface. У цьому випадку CGLIB створює підклас класу @Configuration і замінює його методи (включаючи метод @Bean). Таким чином, коли ми викликаємо метод @Bean з іншого методу, ми фактично викликаємо його перевизначену версію (завдяки динамічному прив'язуванню Java).
Flame239

Тож чи буде функція selfInvocation AOP in @Componentпрацювати, якщо я використовую CHLIB для створення проксі-серверів замість Java Poxy?
Antoniossss
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.