Spring. Первые шаги
Spring Framework (сокр. Spring) - фреймворк для разработки энтерпрайз приложений. Спринг позволяет создавать масштабируемые и легко поддерживаемые решения, что сильно ускоряет разработку.
Данный фреймворк имеет высокую модульность, каждый модуль способен запускаться и выполнять свои задачи как самостоятельное приложение, либо же может использоваться в группе с другими модулями (фреймворки в фреймворке). Функционал спринга постоянно обновляется и дополняется, наиболее популярные модули реализуют функционал MVC, работы с базой данных, секьюрности приложений, обмена сообщений, шаблонизаторов и многого другого.
Как это работает
Bean - объект, управляемый спрингом. В спринге все будет бинами: и сервисы, и ДАО, и контроллеры (группы сервлетов).
DI-контейнер - технология, держащая в себе бины и отвечающая за их связь. Например дао подтягивать к сервису будет именно этот контейнер. Но вашим кодом это не ограничится, контейнер позволит запускать различные модули без жесткой связи между собой, так в модуль Security не потребуется передавать все контроллеры из модуля MVC, контейнер свяжет их неявно.
Контекст - окружение, в котором запускается приложение. Их реализовано более десятка, но чаще всего используется следующие 3 версии
— FileSystemXmlApplicationContext; - xml конфиг, раньше был распространен, сейчас устарел после ввода аннотаций в java 1.6 — AnnotationConfigApplicationContext; - современный контекст, основывается на аннотациях, изучать будем его. — StaticApplicationContext - переходный вариант, прямо в коде связываем бины, используется для тестирования
И в обратную сторону: Контейнер + метаданные (настройки) позволяют запустить образуют ваше приложение с контейнером, который управляет бинами.
Первая задача. HelloWorld.
Всего 3 класса и одна зависимость.
Класс App содержит метод мейн, с которого запускается спринг при создании контекста. В контекст мы передаем класс AppConfig, который помечен аннотацией @Configuration, так спринг понимает, что это настроечный класс.
В классе AppConfig содержится метод, помеченный аннотацией как бин, этот метод будет выполнен при запуске и его результат станет объектом управляемым спрингом.
Класс HelloWorld является обычным джава-классом, мы его используем без каких-либо сложностей.
В методе мейн мы можем получить бин ХеллоВорлд по имени и использовать в любом месте программы.
Спринг позволяет использовать различные типы бинов, одни будут жить от старта до завершения программы, другие будут создаваться при каждом реквесте или открытии новой сессии, третьи при каждом вызове будут создаваться новые. За это отвечает аннотация @Scope.
Задание:
- Прочитайте про виды бинов
- Создайте POJO-class Cat
- в кассе AppConfig по аналогии создайте бин с именем “cat”.
- Настройте этот бин так, чтобы он создавался новым при каждом запросе.
- В классе App по аналогии вызовите еще раз бин HelloWorld, затем 2 раза вызовите бин cat. Сравните 2 пары бинов по ссылке и выведите результат в консоль. Для пары хэлловорлдов должно вернуться тру, для кэт - фоллзс. Так вы можете увидеть результат того, как работает наш контейнер.
Задача 2. Spring Beans
Теперь поработаем со связыванием бинов. Вызывать бины из контекста хорошо, но не так удобно, как связывать их автоматически.
Для работы аннотаций связывания, я добавил в мавен ядро спринга, так мы имеем совершенно рабочее спринг приложение, хоть и без дополнительных модулей.
В компоненте AnimalCage есть поле типа Animal, которое связано с помощью аннотации @Autowired. При выполнении программы DI-контейнер потянет сюда бин, подходящий по типу.
Задача:
- Создайте бин Dog, унаследуйте его от Animal. Создайте на основе этого класса компонент.
- Запустите приложение и проверьте, что было выброшено исключение NoUniqueBeanDefinitionException. Это произошло из-за того, что по типу Animal существует 2 бина и спринг выбросит исключение. Прочитайте по связыванию бинов по имени и свяжите AnimalCage c бином Dog через интерфейс Animal.
- На основе класса Timer создайте бин. Свяжите с AnimalCage. Проверьте, что при выполнении метода мейн время, которое пишет таймер, одно и тоже.
Задача 3. Виды связывания бинов.
«На море на океане есть остров, на том острове дуб стоит, под дубом сундук зарыт, в сундуке — заяц, в зайце — утка, в утке — яйцо, в яйце — игла, — смерть Кощея»
Зависимости остались прежние. В упражнении появился компонент Кощей Бессмертный (KoscheiTheDeathless), который расскажет, где находится его смерть, если вызвать метод getRulesByDeth() . Для описания поиска смерти использованы классы в папке models. Для вашего удобства они были пронумерованы: Ocean1, Island2, Wood3 и так далее.
Чтобы спринг видел все бины, в классе AppConfig была добавлена аннотация @ComponentScan.
В спринге связать бины можно различными способами, рассмотрим их на примере:
- KoscheiTheDeathless связывается с Ocean1 через сеттер setOcean и аннотации аутовайрд над ней.
- Ocean1 связан с Island2 через поле и аннотацию, которая подтянет бин Island2 через метод getIsland() в классе AppConfig. Обратите внимание, что данный метод обозначен аннотацией @Bean, что автоматически подтягивает аргументы в метод. В качестве аргумента выступает бин Wood3
- бин Wood3 помечен компонентом, который конструируется через связывание по @Autowired конструктору.
Ваша задача:
Собрать цепочку до 8го элемента, использовав все вышеперечисленные методы связывания. После выполнения вы должны получить полную фразу.
Вопросы для самопроверки:
- Что такое бин
- Виды бинов
- Чем бин отличается от POJO класса?
- Что такое Inversion of Control и как Spring реализует этот принцип.
- Для чего существует такое количество ApplicationContext.
- Как можно связать бины
- Что такое Dependency Injection
- Какие бины будут использоваться для настройки приложения?