Инициализация Spring beans через метод - PullRequest
0 голосов
/ 19 июня 2020

У меня есть небольшой вопрос о создании bean-компонентов, который меня очень беспокоит.

Например, у меня есть классы

public class A {
    B b;
    public A(B b) { 
        this.b = b;
    }
}
public class B {}

И я хочу сделать bean-компоненты для них вот так:

@Configuration 
public class Config {

@Bean
public B beanB() {
    return new B();
}
//version 1
@Bean
public A beanA() {
    return new A(beanB())
}
//version 2
@Bean
public A beanA(B beanB) {
    return new A(beanB)
}
}

Итак, у меня вопрос: как правильно создать bean A?

Я думаю, что правильным является версия 2, потому что в версии 1 я думаю, что beanB может быть вызван 2 раз: о создании beanA и о том, когда весна создаст его для своего контекста. Но я не могу найти ничего, что подтвердило бы мое мнение.

1 Ответ

0 голосов
/ 19 июня 2020

"Правильный" способ - это сделать так, как это показано в документации , т.е. javado c of @Bean:

@Bean Методы в @Configuration Классах

Как правило, @Bean методы объявляются в @Configuration классах. В этом случае методы компонента могут ссылаться на другие @Bean методы в том же классе, вызывая их напрямую . Это гарантирует, что ссылки между компонентами строго типизированы и доступны для навигации. Такие так называемые «межкомпонентные ссылки» гарантированно соблюдают область видимости и семантику АОП, как и getBean() поисковые запросы. Это семантика, известная из исходного проекта Spring JavaConfig, который требует создания подклассов CGLIB для каждого такого класса конфигурации во время выполнения. Как следствие, @Configuration классы и их фабричные методы не должны быть помечены как final или private в этом режиме. Например:

@Configuration
public class AppConfig {

 @Bean
 public FooService fooService() {
     return new FooService(fooRepository());
 }

 @Bean
 public FooRepository fooRepository() {
     return new JdbcFooRepository(dataSource());
 }

 // ...
}

Это означает версию 1 в коде вопроса.

Spring динамически подклассы AppConfig, поэтому создается только один экземпляр независимо от того, сколько раз метод вызывается, например, функционально примерно так:

public class $dynamic$ extends AppConfig {
    private FooRepository cachedFooRepository;

    @Override
    public FooRepository fooRepository() {
        if (this.cachedFooRepository == null)
            this.cachedFooRepository = super.fooRepository();
        return cachedFooRepository;
    }
}
...