applicationcontext spring что это

Spring: в поисках контекста

Пару месяцев назад в моем профиле был опубликован подробный пост по загрузке классов на JVM. После этого доклада мои коллеги задались хорошим вопросом: а какой механизм использует Spring для разбора конфигураций и как он загружает классы из контекста?

После многих часов дебага спринговых исходников мой коллега экспериментальным путём докопался до той самой простой и понятной правды.

Немного теории

Сразу определим, что ApplicationContext — это главный интерфейс в Spring-приложении, который предоставляет информацию о конфигурации приложения.

Перед тем, как перейти непосредственно к демонстрации, взглянем на этапы формирования ApplicationContext:

В этом посте разберем первый этап, так как нас интересует именно чтение конфигураций и создание BeanDefinition.

BeanDefinition — это интерфейс, который описывает бин, его свойства, аргументы конструктора и другую метаинформацию.

Что касается конфигурации самих бинов, у Spring есть 4 способа конфигурации:

Xml конфигурация

За основу берем простой проект:

Здесь следует немного пояснить, какие методы и для чего используются:

В 25 строке идет объявление и инициализация ApplicationContext через конфигурацию Xml.

Конфигурационный Xml-файл выглядит следующим образом:

При конфигурации бина указываем реально существующий class. Обратите внимание на заданное свойство lazy-init=”true”: в этом случае бин будет создаваться только после запроса его из контекста.

Смотрим, как Spring при поднятии контекста разрулит ситуацию с классами, объявленными в конфигурационном файле:

Разберемся с деталями Xml конфигурации:

— Чтением файла конфигурации занимается класс XmlBeanDefinitionReader, который реализует интерфейс BeanDefinitionReader;

XmlBeanDefinitionReader на входе получает InputStream и загружает Document через DefaultDocumentLoader:

— После этого каждый элемент этого документа обрабатывается и, если он является бином, создается BeanDefinition на основе заполненных данных (id, name, class, alias, init- method, destroy-method и др.):

— Каждый BeanDefinition помещается в Map, который хранится в классе DefaultListableBeanFactory:

В коде Map выглядит следующим образом:

Теперь в том же конфигурационном файле добавим еще одно объявление бина с классом film.BadVillain:

Смотрим, что получится, если распечатать список созданных BeanDefenitionNames и загруженные классы:

Несмотря на то, что класса film.BadVillain, указанного в конфигурационном файле, не существует, Spring отрабатывает без ошибок:

Cписок BeanDefenitionNames содержит 2 элемента; то есть, те 2
BeanDefinition, сконфигурированные в нашем файле, были созданы.

Конфигурации обоих бинов, по сути, одинаковы. Но, при этом существующий класс загрузился, никаких проблем не возникло. Из чего можно сделать вывод, что попытка загрузить несуществующий класс также была, но провальная попытка ничего не сломала.

Попытаемся получить еще и сами бины по их именам:

Если в первом случае был получен валидный бин, то во втором случае прилетел exception.

Обратите внимание на stack trace: сработала отложенная загрузка классов. Выполняется обход всех загрузчиков классов в попытке найти искомый класс среди загруженных ранее. И после того, как нужный класс не был найден, с помощью вызова метода Utils.forName, происходит попытка найти несуществующий класс по имени, что привело к получению закономерной ошибки.

При поднятии контекста загрузился только один класс, при этом попытка загрузки несуществующего файла не привела к ошибке. Почему так произошло?

Всё потому, что мы прописали lazy-init:true и запретили Spring создавать экземпляр бина, где и генерируется полученный ранее exception. Если убрать это свойство из конфигурации либо изменить его значение lazy-init:false, то описанная выше ошибка также вылетит, но не будет проигнорирована и приложение остановиться. В нашем случае контекст был проинициализирован, но мы не смогли создать экземпляр бина, т.к. указанный класс не был найден.

Groovy конфигурация

При конфигурации контекста с помощью Groovy-файла, необходимо сформировать GenericGroovyApplicationContext, который принимает на вход строку с конфигурацией контекста. Чтением контекста в данном случае занимается класс GroovyBeanDefinitionReader. Эта конфигурация работает по сути так же, как и Xml, только с Groovy-файлами. К тому же, GroovyApplicationContext нормально работает и с Xml-файлом.

Пример простого конфигурационного Groovy-файла:

Пробуем проделать то же самое, что и с Xml:

Ошибка вылетает сразу: Groovy так же, как и Xml, создает BeanDefenition’ы, но в данном случае постпроцессор сразу выдаёт ошибку.

Конфигурация через аннотации с указанием пакета для сканирования или JavaConfig

Данная конфигурация отличается от двух предыдущих. В конфигурация через аннотации используется 2 варианта: JavaConfig и аннотация над классами.

Здесь используется один и тот же контекст: AnnotationConfigApplicationContext(“package”/JavaConfig.class). Работает он в зависимости от того, что было передано в конструктор.

Читайте также:  хорошо быть мужчиной а женщины так не могут

В контексте AnnotationConfigApplicationContext есть 2 приватных поля:

Создаем конфигурационный файл с максимально простым бином. Смотрим, что загрузится:

Если в случае с Xml и Groovy загрузилось столько BeanDefinition, сколько было объявлено, то в данном случае в процессе поднятия контекста загружаются как объявленные, так и дополнительные BeanDefinition. В случае реализации через JavaConfig все классы загружаются сразу, в том числе и класс самого JavaConfig, так как он сам является бином.

Еще один момент: в случае с Xml и Groovy конфигурациями загрузилось 343 файла, здесь же произошла более “тяжелая” загрузка количеством 631 доп файл.

Этапы работы ClassPathBeanDefinitionScanner:

Рассмотрим работу сканера на простом примере.

Создаем собственную аннотацию для поиска соответствующих классов:

Создаем 2 класса: один со стандартной аннотацией Component, второй — с кастомной аннотацией:

В результате получаем сформированные BeanDefinition для этих классов и успешно загруженные классы.

Вывод

Из всего вышесказанного на поставленные вопросы можно ответить следующим образом:

Источник

Что такое контекст Spring и как его создать?

Контекст (а у него есть даже интерфейс — org.springframework.context.ApplicationContext ) — это некоторое окружение, в котором работает приложение на Spring Framework. Страшные аббревиатуры DI, IoC — это всё про него. Собственно, контекст создаёт и хранит экземпляры классов вашего приложения, определяет их зависимости друг с другом и автоматически их задаёт.

Безусловно, для того чтобы Spring создал контекст с экземплярами классов, ему нужно предоставить дополнительную информацию — мета-данные, из каких классов/объектов состоит ваше приложение, как они создаются, какие у них есть зависимости и т. д.

Итого: Spring Context + мета-данные = работающее приложение.

Где найти контекст?

Контекст является ключевой функциональностью Spring и лежит в maven-зависимости spring-context (на момент написания — org.springframework:spring-context:5.1.4.RELEASE ). Обычно эта зависимость является транзитивной для остальных проектов Spring. И если вы, например, подключаете spring-boot-starter, то она подключится автоматически, и не нужно думать про то, где её взять.

Но если вы хотите попробовать «голый» Spring, т. е. только ту часть, которая называется IoC-контейнер, то достаточно подключить лишь spring-context.

Какие бывают контексты и как их создать?

У интерфейса ApplicationContext есть большое количество реализаций: — ClassPathXmlApplicationContext ; — FileSystemXmlApplicationContext ; — GenericGroovyApplicationContext ; — AnnotationConfigApplicationContext ; — и даже StaticApplicationContext ; — а также некоторые другие.

Они отличаются друг от друга именно тем, каким способом задаются мета-данные и где хранится эта конфигурация. Например: — ClassPathXmlApplicationContext — метаданные конфигурируются XML-файлом(-ами) и они лежат в classpath, т. е. в ресурсах модуля; — FileSystemXmlApplicationContext — метаданные тоже конфигурируются XML-файлом(-ами), но они находятся где-то в файловой системе, например, /etc/yourapp/spring-context.xml ; — AnnotationConfigApplicationContext — метаданные конфигурируются с помощью аннотаций прямо на классах.

Современным способом конфигурирования считаются аннотации ( AnnotationConfigApplicationContext ), дальше будем создавать именно их.

Приведём пример создания такого контекста в методе main:

Итого: создаём контекст.

Следите за новостями, оставляйте комментарии и посмотрите программу курса «Разработчик на Spring Framework», вдруг захочется погрузится полностью!

Источник

Русские Блоги

Поговорим о BeanFactory и ApplicationContext во фреймворке Spring

Spring описывает отношения зависимости между Bean и Bean через файл конфигурации и использует функцию отражения Java для создания экземпляра Bean и установления отношения зависимости между Beans. Контейнер IoC Sprig также предоставляет расширенные услуги, такие как кэширование экземпляра компонента, управление жизненным циклом, прокси-сервер экземпляра компонента, публикация событий и загрузка ресурсов на основе выполнения этих основных задач.

Контекст приложения (com.springframework.context.ApplicationContext) основан на BeanFactory и предоставляет больше функций, ориентированных на приложения. Он обеспечивает поддержку интернационализации и систему событий каркаса, упрощая создание практических приложений.

1 BeanFactory

1.1 Архитектура классов

Существует множество реализаций BeanFactory. В версиях до Spring 3.2 наиболее часто используется XmlBeanFactory, который теперь является устаревшим. Рекомендуется использовать XmlBeanDefinitionReader и DefaultListableBeanFactory.

Интерфейс BeanFactory находится наверху дерева структуры класса. Его основным методом является getBean (String beanName), который возвращает объект Bean с определенным именем из контейнера. Функции BeanFactory постоянно расширяются с помощью других интерфейсов.

интерфейс Описание
ListableBeanFactory Этот интерфейс определяет несколько методов доступа к основной информации о компоненте в контейнере, например, просмотр количества компонентов, получение имени конфигурации определенного типа компонента или проверка того, содержит ли контейнер определенный компонент.
HierarhicalBeanFactory Интерфейс родительско-дочернего каскадного контейнера IoC, дочерний контейнер может получить доступ к родительскому контейнеру через метод интерфейса.
ConfigurableBeanFactory Этот интерфейс расширяет возможности настройки контейнера IoC. Он определяет такие методы, как загрузчик классов, редактор свойств, постпроцессор инициализации контейнера и т. Д.
AutowireCapableBeanFactory Определяет метод автоматической сборки компонента в контейнере в соответствии с определенными правилами (например, сопоставление по имени, сопоставление по типу).
SingletonBeanFactory Определяет методы, позволяющие регистрировать одноэкземплярные bean-компоненты в контейнере во время выполнения.
BeanDefinitionRegistry Каждый элемент узла Bean в файле конфигурации Spring представлен объектом BeanDefinition в контейнере Spring, который описывает информацию о конфигурации Bean. Интерфейс BeanDefinitionResgistry предоставляет метод для ручной регистрации объектов BeanDefinition в контейнере.

1.2 Инициализация

Затем мы настраиваем Bean People в файле конфигурации Spring, затем загружаем файл конфигурации через BeanFactory и запускаем контейнер Ioc.

Файл конфигурации Spring:

Затем используйте DefaultListableBeanFactory и XmlBeanDefinitionReader для запуска контейнера Ioc:

XmlBeanDefinitionReader загружает информацию о конфигурации Spring через Resource и запускает контейнер Ioc, а затем вы можете получить Bean через BeanFactory # getBean (name). Инициализация компонента происходит при его первом вызове. Для одноэкземплярных bean-компонентов BeanFactory кэширует экземпляр Bean, поэтому второе использование метода getBean () будет напрямую получать экземпляр Bean из кеша контейнера IoC.

Примечание: При инициализации BeanFactory для него должна быть предоставлена ​​структура журнала.Обычно используется Log4J, то есть файл конфигурации Log4J предоставляется в пути к классам, так что контейнер Spring можно запустить в обычном режиме.

2 ApplicationContext

ApplicationContext является производным от BeanFactory и предоставляет множество практических функций приложения. В BeanFactory многие функции должны быть реализованы программно, а в ApplicationContext они могут быть реализованы через конфигурацию.

2.1 Архитектура класса ApplicationContext

интерфейс Описание
ApplicationEventPublisher Позвольте контейнеру иметь функцию публикации событий контекста приложения, включая события запуска контейнера и события завершения работы. Компоненты, реализующие интерфейс мониторинга событий ApplicationListener, могут получать события контейнера и отвечать на события контейнера. В абстрактном классе реализации AbstractApplicationContext ApplicationContext есть ApplicationEventMulticaster, который отвечает за сохранение всех слушателей, чтобы они могли получать уведомления, когда контейнер генерирует события контекста.
MessageSource Предоставляет функцию международного доступа к информации i18n для контейнера.
ResourcePatternResolver Все классы реализации ApplicationContext имеют реализованные функции, аналогичные PathMatchingResourcePatternResolver, а файлы конфигурации Spring могут быть загружены с помощью префиксов пути к файлам классов ресурсов в стиле Ant.
LifeCycle Он предоставляет два метода, start () и stop (), которые в основном используются для управления асинхронной обработкой. При конкретном использовании этот интерфейс реализуется как ApplicationContext, так и конкретным Bean. ApplicationContext будет передавать информацию о запуске / остановке всем bean-компонентам в контейнере, которые реализуют этот интерфейс для достижения цели управления и контроля JMX и планирования задач.
ConfigurableApplicationContext Он расширяет ApplicationContext, давая ApplicationContext возможность запускать, обновлять и закрывать контекст приложения. Когда контекст закрыт, вызовите refresh (), чтобы запустить контекст; если он уже запущен, вызовите refresh (), чтобы очистить кеш и перезагрузить информацию о конфигурации; вызовите close (), чтобы закрыть контекст приложения.

2.1.1 Конфигурация XML

При инициализации ApplicationContext выберите класс реализации ApplicationContext в соответствии с путем к файлу конфигурации.

Вы также можете указать набор файлов конфигурации, и Spring автоматически интегрирует содержимое нескольких файлов конфигурации:

Примечание. ClassPathXmlApplicationContext и FileSystemXmlApplicationContext также могут явно указывать путь с префиксом типа ресурса.

2.1.2 Конфигурация аннотации класса

Spring поддерживает настройку на основе аннотаций классов.Основная функция происходит из подпроекта Spring под названием JavaConfig. В настоящее время JavaConfig обновлен до части основной инфраструктуры Spring. POJO с аннотацией @Configuration может предоставить информацию о конфигурации Bean, требуемую Spring.

По сравнению с методом конфигурации XML, метод конфигурации, основанный на аннотации класса, позволяет разработчикам управлять процессом инициализации компонента, поэтому он более гибкий.

Конфигурация компонента на основе аннотаций класса должна использовать AnnotationConfigApplicationContext для запуска контейнера Spring:

2.1.3 Конфигурация Groovy DSL

Spring 4.x поддерживает использование Groovy DSL для настройки компонентов, с помощью которых может быть реализована сложная и гибкая логика конфигурации.

Сначала введите Groovy в pom.xml:

Затем добавьте файл конфигурации:

Наконец, используйте GenericGroovyApplicationContext для запуска контейнера:

2.2 Архитектура класса WebApplicationContext

WebApplicationContext предназначен для веб-приложений. Он позволяет загружать файл конфигурации из пути относительно корневого веб-каталога для завершения работы по инициализации. Ссылку на ServletContext можно получить из WebApplicationContext. Весь объект контекста веб-приложения будет помещен в качестве атрибута в ServletContext, чтобы веб-приложение могло Для доступа к контексту Spring Spring предоставляет метод getWebApplicationContext (ServletContext src) для WebApplicationContextUtils для получения экземпляра WebApplicationContext из ServletContext.

В среде приложений, отличных от веб-приложений, Bean имеет только две области: одноэлементную и прототипную. В WebApplicationContext он добавляет к Бину еще три области: запрос, сеанс и глобальный сеанс.

WebApplicationContext расширяет ApplicationContext. WebApplicationContext определяет константу ROOT_WEB_APPLICATION_ CONTEXT_ATTRIBUTE. Когда контекст запускается, экземпляр WebApplicationContext использует эту константу в качестве ключа и помещается в список атрибутов ServletContext. Таким образом, мы можем напрямую получить WebApplicationContext из веб-контейнера с помощью следующего оператора:

ConfigurableWebApplicationContext расширяет WebApplicationContext, что позволяет создавать экземпляр WebApplicationContext через конфигурацию, и определяет два важных метода:

Название метода Описание
setServletContext(ServletContext servletContext) Настройте контекст веб-приложения для Spring для интеграции двух
setConfigLocations(String[] configLocations) Задайте адрес файла конфигурации Spring. Как правило, адрес файла конфигурации зависит от адреса корневого веб-каталога, например /WEB-INF/config.xml. Однако пользователи также могут использовать адреса с префиксом типа ресурса, например classpath: net / deniro / beans.xml.

2.3 Инициализировать контекст WebApplicationContext

WebApplicationContext требуется экземпляр ServletContext, у него должен быть веб-контейнер, чтобы завершить начальную работу. Мы можем настроить самозапускающийся сервлет или определить прослушиватель веб-контейнера (ServletContextListener) в web.xml. С помощью одного из этих двух элементов мы можем запустить контекст веб-приложения Spring.

нота: Все версии веб-контейнеров поддерживают самозапускающийся сервлет, но только веб-контейнеры Servlet 2.3 и выше поддерживают слушателей веб-контейнеров. Но некоторые веб-контейнеры являются исключением, например Weblogic 8.1, WebSphere 5.x, Oracle OC4J 9.0 и так далее.

Spring предоставляет прослушиватель сервлетов и веб-контейнеров для запуска WebApplicationContext:
* org.springframework.web.context.ContextLoaderServlet。
* org.springframework.web.context.ContextLoaderListener。

2.3.1 XML-метод

Давайте запустим WebApplicationContext с помощью ContextLoaderListener:

ContextLoaderListener получает местоположение файла конфигурации Spring через параметр контекста веб-контейнера contextConfigLocation. Вы можете указать несколько файлов конфигурации, и вы можете использовать запятые, пробелы или двоеточия для их разделения. Для путей к файлам без префикса типа ресурса WebApplicationContext будет по умолчанию использовать эти пути как корневой путь развертывания в Интернете. Конечно, вы также можете использовать конфигурацию пути с префиксом типа ресурса, например здесь classpath*:spring-*.xml 。

Если вы находитесь в веб-контейнере с низкой версией, который не поддерживает прослушиватели контейнеров, мы можем использовать ContextLoaderServlet для завершения работы по запуску, поскольку Spring 4 больше не поддерживает этот класс, поэтому мы не будем его повторять.

Поскольку WebApplicationContext должен использовать журнал, мы помещаем файл конфигурации Log4J в путь к классам WEB-INF / classes, чтобы механизм Log4J мог запускаться плавно. Если файл конфигурации Log4J находится в другом месте, вы должны указать расположение файла конфигурации Log4J в web.xml. Spring предоставляет два класса реализации, аналогичные запуску WebApplicationContext для включения механизма Log4J: Log4jConfigServlet (больше не поддерживается в Spring4) и Log4jConfigListener. Независимо от того, какой метод используется, необходимо убедиться, что информация о конфигурации Log4J может быть загружена до загрузки файла конфигурации Spring.

нота: Log4jConfigListener должен быть помещен перед ContextLoaderListener, чтобы гарантировать, что первый запускается первым, завершает загрузку файла конфигурации Log4J и инициализирует механизм Log4J, а затем запускает последний.

2.3.2 Метод аннотации

Вы также можете использовать аннотированный Java-класс @Configuration для предоставления информации о конфигурации:

В это время, если ContextLoaderListener находит параметр контекста contextClass, он будет использовать AnnotationConfigWebApplicationContext, указанный параметром, для инициализации контейнера. Класс реализации инициализирует контейнер в соответствии с информацией о конфигурации, предоставленной классом конфигурации @Configuration, указанным параметром contextConfigLocation.

2.3.3 Groovy DSL способ

Вы также можете использовать метод Groovy DSL, принцип аналогичен методу аннотации.

2.4 родительско-дочерний контейнер

Через интерфейс HierarchicalBeanFactory контейнер IoC Spring может установить иерархическую систему контейнеров «родитель-потомок». Дочерний контейнер может получить доступ к Bean в родительском контейнере, но родительский контейнер не может получить доступ к Bean дочернего контейнера. Внутри контейнера идентификатор bean-компонента должен быть уникальным, но дочерний контейнер может иметь bean-компонент с тем же идентификатором, что и родительский контейнер. Иерархия родительско-дочерних контейнеров повышает масштабируемость и гибкость контейнерной архитектуры Spring, поэтому третьи стороны могут программно добавлять один или несколько дочерних контейнеров специального назначения к существующему контейнеру для обеспечения некоторых дополнительных функций.

Spring использует характеристики родительско-дочерних контейнеров для достижения многих возможностей.Например, в Spring MVC Бин уровня представления расположен в дочернем контейнере, а Бины бизнес-уровня и уровня сохраняемости расположены в родительском контейнере. Таким образом, Бин уровня представления может относиться к бизнес-уровню и Бину уровня сохраняемости, но Бин бизнес-уровня и Бин уровня сохраняемости не может видеть Бин уровня представления.

Источник

Читайте также:  что делать если idle master не подключается к steam
Сказочный портал