Что такое Inversion of Control в Spring
Что проверяют
Отличаете ли вы принцип от механизма: IoC это идея, внедрение зависимостей один из способов её реализовать, а контейнер Spring конкретный инструмент. Следом почти всегда спрашивают, почему конструкторное внедрение лучше полевого и что Spring делает с циклическими зависимостями.
Как отвечать
Инверсия контроля означает, что класс не управляет созданием своих зависимостей: он объявляет, что ему нужно, а собирает всё внешняя сторона. Это шире DI: колбэки, шаблонный метод и обработчики событий тоже инвертируют управление.
В Spring это устроено так:
- контейнер:
ApplicationContext, надстройка надBeanFactory. Он читает конфигурацию (сканирование@Component, классы@Configurationс методами@Bean), строитBeanDefinition, создаёт объекты и связывает их; - внедрение через конструктор: рекомендуемый вариант. Если конструктор один,
@Autowiredписать не нужно, так работает со Spring 4.3. Поля можно сделатьfinal, а объект создаётся в тесте обычнымnewс моками, без поднятия контекста; - сеттер и поле: сеттер уместен для необязательных зависимостей, полевое
@Autowiredпрячет зависимости и не даёт сделать полеfinal; - выбор реализации: если подходят два бина, будет
NoUniqueBeanDefinitionException, решается через@Primaryили@Qualifier; - прокси:
@Transactional,@Async,@Cacheableработают только потому, что объект создаёт контейнер и может подменить его прокси.
Про циклы: начиная со Spring Boot 2.6 циклические зависимости по умолчанию запрещены, и приложение не стартует. Вернуть старое поведение можно через spring.main.allow-circular-references=true, но правильнее разорвать цикл.
Где спотыкаются
Ставят знак равенства между IoC и DI и не могут привести пример инверсии без внедрения зависимостей.
Создают объект через new в обход контейнера и удивляются, что его @Autowired-поля остались null. Контейнер про такой объект ничего не знает.
Вызывают @Transactional-метод из другого метода того же класса и не понимают, почему транзакции нет. Вызов идёт через this, мимо прокси, поэтому аннотация не срабатывает.