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


Читайте также:


Комментарии

Популярные сообщения из этого блога

Методы класса Object в Java

Как получить текущий timestamp в Java

Основные опции JVM для повышения производительности и отладки