Spring IoC контейнер: Java конфигурация, использование аннотации @Configuration, о внутренней работе конфигурации на основе Java
Рассмотрим следующий пример, который показывает, что аннотированный метод @Bean вызывается дважды:
Java
@Configuration
public class AppConfig {
@Bean
public ClientService clientService1() {
ClientServiceImpl clientService = new ClientServiceImpl();
clientService.setClientDao(clientDao());
return clientService;
}
@Bean
public ClientService clientService2() {
ClientServiceImpl clientService = new ClientServiceImpl();
clientService.setClientDao(clientDao());
return clientService;
}
@Bean
public ClientDao clientDao() {
return new ClientDaoImpl();
}
}
Kotlin
@Configuration
class AppConfig {
@Bean
fun clientService1(): ClientService {
return ClientServiceImpl().apply {
clientDao = clientDao()
}
}
@Bean
fun clientService2(): ClientService {
return ClientServiceImpl().apply {
clientDao = clientDao()
}
}
@Bean
fun clientDao(): ClientDao {
return ClientDaoImpl()
}
}
clientDao() был вызван один раз в clientService1() и один раз в clientService2(). Поскольку этот метод создает новый экземпляр ClientDaoImpl и возвращает его, обычно предполагается наличие двух экземпляров (по одному для каждой службы). Это определенно было бы проблематично: в Spring по умолчанию созданные бинов имеют одноэлементную (singleton) область действия. В этом и заключается волшебство: для всех классов @Configuration создаются подклассы во время запуска с помощью CGLIB. В подклассе дочерний метод сначала проверяет контейнер на наличие кэшированных (бинов с областями дествия) bean-компонентов, прежде чем он вызовет родительский метод и создаст новый экземпляр.
Поведение может отличаться в зависимости от области действия вашего bean-компонента. Здесь мы говорим о синглтонах.
Начиная с Spring 3.2, больше нет необходимости добавлять CGLIB в путь к классам, поскольку классы CGLIB были переупакованы в org.springframework.cglib и включены непосредственно в JAR-файл spring-core.
Есть несколько ограничений из-за того, что CGLIB динамически добавляет функции во время запуска. В частности, классы конфигурации не должны быть final. Однако, начиная с 4.3, в классах конфигурации разрешены любые конструкторы, включая использование @Autowired или одного объявления конструктора не по умолчанию для внедрения по умолчанию.
Если вы предпочитаете избегать любых ограничений, накладываемых CGLIB, рассмотрите возможность объявления ваших @Bean-методов в классах, отличных от @Configuration (например, вместо этого в простых классах @Component). При этом перекрестные вызовы между методами @Bean не перехватываются, поэтому вам придется полагаться исключительно на внедрение зависимостей на уровне конструктора или метода.
Читайте также:
- Spring IoC контейнер: Java конфигурация, настройка имен, псевдонимов, описаний бинов
- Spring IoC контейнер: Java конфигурация, использование аннотации @Configuration, внедрение зависимостей между компонентами
- Spring IoC контейнер: Java конфигурация, использование аннотации @Configuration, внедрение метода поиска
Комментарии
Отправить комментарий