Принцип IoC и Spring

в 16:38, , рубрики: ioc, java, spring, метки: , ,

Часто на собеседовании на вопрос: «Что такое Spring?» приходится слышать «Это какой-то набор библиотек». В принципе отвечающий прав. Но для устройства на работу надо знать, какой именно. В этом небольшом очерке попытаюсь доступно и доходчиво описать, что собой представляет контейнер IoC из Spring Core, c которого надо начинать знакомство со Spring.

Принцип Inversion of Control (IoC) гласит: программировать надо на интерфейсах, а не на их реализациях.

Применяя IoC, уменьшается количество изменяемого кода при изменении логики. К примеру, пишется некая система, отражающая работу оркестра. В оркестре есть скрипач, представленный классом Violinist. Объекты этого класса присутствуют в разных местах логики приложения. И вдруг выясняется, что скрипки публике больше не интересны, и они хотели бы услышать исполнение партии скрипача на бас-гитаре. Что делать? Можно пройти по всем классам и изменить Violinist на Guitarist, поменять везде использование. А что будет, если публика вскоре захочет услышать арфистку? Или чтобы часть партии исполнил скрипач, а часть – гитарист?

Каждый раз перерывать весь код неудобно. Более правильный подход – во всей логике использовать интерфейс вместо класса (например, StringedInstrumentMusician). Тогда при изменении используемого объекта надо будет изменить только место, где инициализируется интерфейс. А при необходимости в одном классе можно инициализировать интерфейс экземпляром одного класса, а в другом – другого.

С интерфейсами стало значительно удобнее. Но можно продолжить улучшения. Можно написать для каждого интерфейса по фабрике, которая возвращала бы тот или иной объект.

Хорошо. Но сама по себе инициализация – процесс одинаковый для всех объектов. И всё фабрики имели бы одинаковую структуру, но представляли бы мало интереса для программиста – просто кусок дублирующегося кода.

И тут на помощь приходит контейнер IoC из Spring. Он берет заботу об инициализации объектов на себя. Фабрики больше не нужны. И кроме того берет на себя управление жизненным циклом каждого бина.

IoC можно сконфигурировать двумя способами: c помощью XML или аннотациями. Конфигурация в XML рассматриваться не будет, т.к. сейчас она актуальна только для старых проектов.

В Spring IoC существуют 4 аннотации, которыми помечаются классы:

@Component
@Service
@Controller
@Repository

Все аннотации делают ровно одно и то же, есть разница только в смысле: @Component означает какой-то абстрактный бин, @Service служит для обозначения сервисов, @Controller – контроллеров из Spring MVC, @Repository – для обозначения репозиториев или DAO (по Фаулеру репозиторий – это фасад для нескольких DAO, но на практике часто вместо написания своей аннотации используют Repository для DAO). Делать 4 аннотации вместо одной имеет смысл ещё потому, что с помощью аспектов из Spring AOP можно обратиться ко всем классам конкретного слоя по аннотации, например, к DAO, чтобы изменить их поведение, например, добавить логирование, специфичное только для слоя DAO.

Для того чтобы класс, помеченный такой аннотацией смог участвовать в инициализации, в контексте Spring отмечается путь, по которому Spring будет искать кандидатов для wiring-а.

И, наконец, самое главное: когда надо инициализировать интерфейс каким-то классом, используется следующая конструкция:

@Autowired
private StringedInstrumentMusician stringedInstrumentMusician;

Аннотация Autowired означает, что будет произведен поиск среди всех реализаций интерфейса StringedInstrumentMusician, помеченных как @Component (@Service, …), и если найден ровно 1 кандидат на wiring, stringedInstrumentMusician будет инициализирован им. Если не найден – будет exception. Указав @Autowired(required=false), можно этого exception-а избежать. Если классов будет несколько (как у нас), то тоже будет выкинут exception: надо указать конкретную реализацию:

@Autowired
@Qualifier(“violinist”)
private StringedInstrumentMusician stringedInstrumentMusician;

Теперь при необходимости изменить исполнителя на струнных инструментах, надо только поменять имя в Qualifier.
В Spring все бины по умолчанию считаются синглтонами. Т.е., указав в разных классах кода инициализацию одного и того же интерфейса, мы будем иметь дело с одним и тем же объектом: он создастся только 1 раз при первом обращении.

Spring — очень удобный и достаточно простой инструмент. В данной статье не ставилось целью описать все нюансы работы IoC, для этого можно обратиться к документации по Spring, она подробная. Целью было написать введение для тех, кто хочет начать знакомство со Spring-ом. Надеюсь, статья окажется полезной.

Автор: mrmaxim


  1. Георгий:

    Бро, большое тебе С П А С И Б О) Наконец нашел короткую и понятную статью!

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js