1. Обзор
В этом руководстве мы подробно рассмотрим интерфейс Spring ApplicationContext .
2. Интерфейс ApplicationContext
Одной из основных особенностей среды Spring является контейнер IoC (Inversion of Control). Контейнер Spring IoC отвечает за управление объектами приложения. Он использует внедрение зависимостей для достижения инверсии управления.
Интерфейсы BeanFactory
и ApplicationContext
представляют контейнер Spring IoC . Здесь BeanFactory
— это корневой интерфейс для доступа к контейнеру Spring. Он предоставляет базовые функции для управления bean-компонентами.
С другой стороны, ApplicationContext
является подинтерфейсом BeanFactory
. Таким образом, он предлагает все функции BeanFactory.
Кроме того, он предоставляет больше функций, специфичных для предприятия . Важными функциями ApplicationContext
являются разрешение сообщений, поддержка интернационализации, публикация событий и специфические контексты прикладного уровня . Вот почему мы используем его в качестве контейнера Spring по умолчанию.
3. Что такое Spring Bean?
Прежде чем мы углубимся в контейнер ApplicationContext
, важно знать о компонентах Spring. В Spring bean -компонент — это объект, который создает, собирает и управляет контейнером Spring .
Итак, должны ли мы настраивать все объекты нашего приложения как компоненты Spring? Ну, в качестве лучшей практики, мы не должны.
В соответствии с документацией Spring в целом мы должны определить bean-компоненты для объектов сервисного уровня, объектов доступа к данным (DAO), объектов представления, объектов инфраструктуры, таких как Hibernate SessionFactories,
JMS Queues и т. д.
Кроме того, как правило, нам не следует настраивать мелкие объекты домена в контейнере. Обычно за создание и загрузку объектов предметной области отвечают DAO и бизнес-логика.
Теперь давайте определим простой класс Java, который мы будем использовать в качестве bean-компонента Spring в этом руководстве:
public class AccountService {
@Autowired
private AccountRepository accountRepository;
// getters and setters
}
4. Настройка компонентов в контейнере
Как мы знаем, основной задачей ApplicationContext
является управление bean-компонентами.
Таким образом, приложение должно предоставить конфигурацию компонента контейнеру ApplicationContext .
Конфигурация bean-компонента Spring состоит из одного или нескольких определений bean-компонентов. Кроме того, Spring поддерживает различные способы настройки bean-компонентов.
4.1. Конфигурация на основе Java
Во-первых, мы начнем с конфигурации на основе Java, так как это самый новый и наиболее предпочтительный способ настройки bean-компонентов. Он доступен начиная с Spring 3.0.
Конфигурация Java обычно использует аннотированные методы @Bean
в классе @Configuration
. Аннотация @Bean
к методу указывает, что метод создает bean-компонент Spring. Более того, класс с аннотацией @Configuration
указывает, что он содержит конфигурации bean-компонентов Spring.
Теперь давайте создадим класс конфигурации, чтобы определить наш класс AccountService
как bean-компонент Spring:
@Configuration
public class AccountConfig {
@Bean
public AccountService accountService() {
return new AccountService(accountRepository());
}
@Bean
public AccountRepository accountRepository() {
return new AccountRepository();
}
}
4.2. Конфигурация на основе аннотаций
Spring 2.5 представил конфигурацию на основе аннотаций в качестве первого шага к включению конфигураций bean-компонентов в Java.
В этом подходе мы сначала включаем конфигурацию на основе аннотаций через конфигурацию XML. Затем мы используем набор аннотаций в наших классах, методах, конструкторах или полях Java для настройки bean-компонентов. Некоторыми примерами этих аннотаций являются @Component
, @Controller
, @Service
, @Repository
, @Autowired
и @Qualifier
.
Примечательно, что мы также используем эти аннотации с конфигурацией на основе Java. Также стоит упомянуть, что Spring продолжает добавлять новые возможности к этим аннотациям с каждым выпуском.
Теперь давайте посмотрим на простой пример этой конфигурации.
Во-первых, мы создадим XML-конфигурацию user-bean-config.xml
, чтобы включить аннотации:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.foreach.applicationcontext"/>
</beans>
Здесь тег annotation-config
включает сопоставления на основе аннотаций . Тег component-scan
также сообщает Spring, где искать аннотированные классы.
Во-вторых, мы создадим класс UserService
и определим его как компонент Spring, используя аннотацию @Component
:
@Component
public class UserService {
// user service code
}
Затем мы напишем простой тестовый пример для проверки этой конфигурации:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationcontext/user-bean-config.xml");
UserService userService = context.getBean(UserService.class);
assertNotNull(userService);
4.3. Конфигурация на основе XML
Наконец, давайте взглянем на конфигурацию на основе XML. Это традиционный способ настройки bean-компонентов в Spring.
Очевидно, что при таком подходе мы делаем все сопоставления bean-компонентов в конфигурационном XML-файле .
Итак, давайте создадим файл конфигурации XML, account-bean-config.xml
, и определим bean-компоненты для нашего класса AccountService
:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="accountService" class="com.foreach.applicationcontext.AccountService">
<constructor-arg name="accountRepository" ref="accountRepository" />
</bean>
<bean id="accountRepository" class="com.foreach.applicationcontext.AccountRepository" />
</beans>
5. Типы контекста приложения
Spring предоставляет различные типы контейнеров ApplicationContext
, подходящие для различных требований. Это реализации интерфейса ApplicationContext .
Итак, давайте рассмотрим некоторые распространенные типы ApplicationContext
.
5.1. AnnotationConfigApplicationContext
Во-первых, давайте посмотрим на класс AnnotationConfigApplicationContext , который был представлен в Spring 3.0.
Он может принимать классы с аннотациями @Configuration
, @Component и
метаданными JSR-330 в качестве входных данных.
Итак, давайте рассмотрим простой пример использования контейнера AnnotationConfigApplicationContext
с нашей конфигурацией на основе Java:
ApplicationContext context = new AnnotationConfigApplicationContext(AccountConfig.class);
AccountService accountService = context.getBean(AccountService.class);
5.2. AnnotationConfigWebApplicationContext
AnnotationConfigWebApplicationContext
— это веб- вариант AnnotationConfigApplicationContext
.
Мы можем использовать этот класс при настройке прослушивателя сервлета Spring ContextLoaderListener
или Spring MVC DispatcherServlet
в файле web.xml
.
Более того, начиная с Spring 3.0, мы также можем настраивать этот контейнер контекста приложения программно. Все, что нам нужно сделать, это реализовать интерфейс WebApplicationInitializer
:
public class MyWebApplicationInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(AccountConfig.class);
context.setServletContext(container);
// servlet configuration
}
}
5.3. XmlWebApplicationContext
Если мы используем конфигурацию на основе XML в веб-приложении , мы можем использовать класс XmlWebApplicationContext
.
По сути, настройка этого контейнера аналогична только классу AnnotationConfigWebApplicationContext
, что означает, что мы можем настроить его в web.xml
или реализовать интерфейс WebApplicationInitializer
:
public class MyXmlWebApplicationInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext container) throws ServletException {
XmlWebApplicationContext context = new XmlWebApplicationContext();
context.setConfigLocation("/WEB-INF/spring/applicationContext.xml");
context.setServletContext(container);
// Servlet configuration
}
}
5.4. FileSystemXMLApplicationContext
Мы используем класс FileSystemXMLApplicationContext
для загрузки файла конфигурации Spring на основе XML из файловой системы или из URL-адресов. Этот класс полезен, когда нам нужно программно загрузить ApplicationContext
. В общем, наборы тестов и автономные приложения являются одними из возможных вариантов использования для этого.
Например, давайте посмотрим, как мы можем создать этот контейнер Spring и загрузить bean-компоненты для нашей конфигурации на основе XML:
String path = "C:/myProject/src/main/resources/applicationcontext/account-bean-config.xml";
ApplicationContext context = new FileSystemXmlApplicationContext(path);
AccountService accountService = context.getBean("accountService", AccountService.class);
5.5. ClassPathXmlApplicationContext
Если мы хотим загрузить файл конфигурации XML из пути к классам , мы можем использовать класс ClassPathXmlApplicationContext .
Подобно FileSystemXMLApplicationContext,
он полезен для тестовых наборов, а также контекстов приложений, встроенных в JAR-файлы.
Итак, давайте посмотрим на пример использования этого класса:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationcontext/account-bean-config.xml");
AccountService accountService = context.getBean("accountService", AccountService.class);
6. Дополнительные возможности ApplicationContext
6.1. Разрешение сообщения
Интерфейс ApplicationContext
поддерживает разрешение и интернационализацию сообщений за счет расширения `` интерфейса MessageSource
. Кроме того, Spring предоставляет две реализации MessageSource
, ResourceBundleMessageSource
и StaticMessageSource
.
Мы можем использовать StaticMessageSource
для программного добавления сообщений в источник; тем не менее, он поддерживает базовую интернационализацию и больше подходит для тестирования, чем для производственного использования.
С другой стороны, ResourceBundleMessageSource
является наиболее распространенной реализацией MessageSource
. Он основан на базовой реализации ResouceBundle
JDK . Он также использует стандартный анализ сообщений JDK, предоставляемый MessageFormat
.
Теперь давайте посмотрим, как мы можем использовать MessageSource
для чтения сообщений из файла свойств.
Во-первых, мы создадим файл messages.properties
в пути к классам:
account.name=TestAccount
Во-вторых, мы добавим определение bean-компонента в наш класс AccountConfig :
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("config/messages");
return messageSource;
}
В-третьих, мы внедрим MessageSource
в AccountService
:
@Autowired
private MessageSource messageSource;
Наконец, мы можем использовать метод getMessage
в любом месте службы AccountService
, чтобы прочитать сообщение:
messageSource.getMessage("account.name", null, Locale.ENGLISH);
Spring также предоставляет класс ReloadableResourceBundleMessageSource
, который позволяет читать файлы из любого расположения ресурса Spring и поддерживает горячую перезагрузку файлов свойств пакета.
6.2. Обработка событий
ApplicationContext
поддерживает обработку событий с помощью класса ApplicationEvent
и интерфейса ApplicationListener
. Он поддерживает встроенные события , такие как ContextStartedEvent
, ContextStoppedEvent
, ContextClosedEvent
и RequestHandledEvent
. Кроме того, он также поддерживает настраиваемые события для бизнес-приложений.
7. Заключение
В этой статье мы обсудили различные аспекты контейнера ApplicationContext
в Spring. Мы также рассмотрели различные примеры того, как настроить bean-компоненты Spring в AppicationContext
. Наконец, мы научились создавать и использовать различные типы ApplicationContext
.
Как всегда, полный код доступен на GitHub .