Spring ApplicationContext

1. Огляд

У цьому посібнику ми детально розглянемо інтерфейс Spring ApplicationConext .

2. Інтерфейс ApplicationContext

Однією з головних особливостей фреймворку Spring є контейнер IoC (Inversion of Control). Контейнер Spring IoC відповідає за управління об'єктами програми. Він використовує введення залежностей для досягнення інверсії контролю.

Інтерфейси BeanFactory і ApplicationContext представляють Spring IoC-контейнер . Тут BeanFactory - це кореневий інтерфейс для доступу до контейнера Spring. Він надає основні функціональні можливості для управління зернами.

З іншого боку, ApplicationContext є підінтерфейсом BeanFactory . Отже, він пропонує всі функціональні можливості BeanFactory.

Крім того, він надає більше функціональних можливостей для конкретного підприємства . Важливими особливостями ApplicationContext є розпізнавання повідомлень, підтримка інтернаціоналізації, публікація подій та конкретний контекст рівня додатків . Ось чому ми використовуємо його як контейнер Spring за замовчуванням.

3. Що таке весняний боб?

Перш ніж заглибитися глибше в контейнер ApplicationContext , важливо знати про весняні боби. Навесні бін - це об’єкт, який контейнер Spring створює, збирає та керує ним .

Отже, чи слід нам конфігурувати всі об’єкти нашого додатку як Spring-зерна? Ну, як найкраща практика, ми не повинні.

Відповідно до документації Spring, загалом, ми повинні визначати компоненти для об’єктів сервісного рівня, об’єктів доступу до даних (DAO), об’єктів презентації, об’єктів інфраструктури, таких як Hibernate SessionFactories, JMS Queue тощо.

Також, як правило, ми не повинні налаштовувати в контейнері детально розміщені об'єкти домену. Зазвичай за створення та завантаження об’єктів домену відповідають DAO та бізнес-логіка.

Отже, давайте визначимо простий клас Java, який ми використовуватимемо як бін Spring у цьому підручнику:

public class AccountService { @Autowired private AccountRepository accountRepository; // getters and setters }

4. Налаштування Beans в контейнері

Як ми знаємо, основна робота ApplicationContext - це управління зернами.

Отже, програма повинна надавати конфігурацію компонента для контейнера ApplicationContext . Отже, конфігурація бобів Spring складається з одного або декількох визначень бобів. Крім того, Spring підтримує різні способи налаштування компонентів.

4.1. Конфігурація на основі Java

По-перше, ми почнемо з конфігурації на основі Java, оскільки це найновіший і найбільш бажаний спосіб конфігурації компонента. Він доступний з версії 3.0 і далі.

Конфігурація Java зазвичай використовує @ Bean-анотовані методи в класі @Configuration . @Bean анотацію на метод показує , що метод створює Spring боб. Більше того, клас, котрий коментується @Configuration, вказує, що він містить конфігурації Spring bean.

Отже, давайте зараз створимо клас конфігурації, щоб визначити наш клас AccountService як Spring Spring:

@Configuration public class AccountConfig { @Bean public AccountService accountService() { return new AccountService(accountRepository()); } @Bean public AccountRepository accountRepository() { return new AccountRepository(); } }

4.2. Конфігурація на основі анотацій

Весна 2.5 представила конфігурацію на основі анотацій як перший крок для увімкнення конфігурацій компонентів у Java.

У цьому підході ми спочатку вмикаємо конфігурацію на основі анотацій через конфігурацію XML. Потім ми використовуємо набір анотацій для наших класів Java, методів, конструкторів або полів для конфігурації файлів. Деякі приклади цих анотацій: @Component , @Controller , @Service , @Repository , @Autowired і @Qualifier .

Примітно, що ми також використовуємо ці анотації з конфігурацією на основі Java. Крім того, Spring продовжує додавати більше можливостей до цих анотацій з кожним випуском.

Отже, давайте побачимо простий приклад цієї конфігурації.

Спочатку ми створимо конфігурацію XML, user-bean-config.xml , щоб увімкнути анотації:

Тут анотація-конфігурація тег дозволяє анотації на основі зіставлення . Крім того, тег сканування компонентів повідомляє 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

Finally, let's take a look at XML-based configuration. It's the traditional way of configuring beans in Spring.

Obviously, in this approach, we do all bean mappings in an XML configuration file.

So, let's create an XML configuration file, account-bean-config.xml, and define beans for our AccountService class:

5. Types of ApplicationContext

Spring provides different types of ApplicationContext containers suitable for different requirements. These are implementations of the ApplicationContext interface. So, let's take a look at some of the common types of ApplicationContext.

5.1. AnnotationConfigApplicationContext

First, let's see the AnnotationConfigApplicationContext class, which was introduced in Spring 3.0. It can take classes annotated with @Configuration, @Component, and JSR-330 metadata as input.

So, let's see a simple example of using the AnnotationConfigApplicationContext container with our Java-based configuration:

ApplicationContext context = new AnnotationConfigApplicationContext(AccountConfig.class); AccountService accountService = context.getBean(AccountService.class);

5.2. AnnotationConfigWebApplicationContext

AnnotationConfigWebApplicationContextis a web-based variant of AnnotationConfigApplicationContext.

We may use this class when we configure Spring's ContextLoaderListener servlet listener or a Spring MVC DispatcherServlet, in a web.xml file.

Moreover, from Spring 3.0 onward, we can also configure this application context container programmatically. All we need to do is to implement the WebApplicationInitializer interface:

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

If we use the XML based configuration in a web application, we can use the XmlWebApplicationContext class.

As a matter of fact, configuring this container is like the AnnotationConfigWebApplicationContext class only, which means we can configure it in web.xml or implement the WebApplicationInitializer interface:

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

We use the FileSystemXMLApplicationContext class to load an XML-based Spring configuration file from the file system or from URLs. This class is useful when we need to load the ApplicationContext programmatically. In general, test harnesses and standalone applications are some of the possible use cases for this.

For example, let's see how we can create this Spring container and load the beans for our XML-based configuration:

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

In case we want to load an XML configuration file from the classpath, we can use the ClassPathXmlApplicationContext class. Similar to FileSystemXMLApplicationContext, it's useful for test harnesses as well as for application contexts embedded within JARs.

So, let's see an example of using this class:

ApplicationContext context = new ClassPathXmlApplicationContext("applicationcontext/account-bean-config.xml"); AccountService accountService = context.getBean("accountService", AccountService.class);

6. Additional Features of ApplicationContext

6.1. Message Resolution

The ApplicationContext interface supports message resolution and internationalization by extending the MessageSource interface. Furthermore, Spring provides two MessageSource implementations, ResourceBundleMessageSource and StaticMessageSource.

We can use the StaticMessageSource to programmatically add messages to the source. However, it supports basic internationalization and is more suitable for tests than production use.

On the other hand, ResourceBundleMessageSource is the most common implementation of MessageSource. It relies on the underlying JDK's ResouceBundle implementation. It also uses the JDK's standard message parsing provided by MessageFormat.

Now, let's see how can we use the MessageSource to read the messages from a properties file.

First, we'll create the messages.properties file on the classpath:

account.name=TestAccount

Second, we'll add a bean definition in our AccountConfig class:

@Bean public MessageSource messageSource() { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasename("config/messages"); return messageSource; }

Third, we'll inject the MessageSource in the AccountService:

@Autowired private MessageSource messageSource;

Finally, we can use the getMessage method anywhere in the AccountService to read the message:

messageSource.getMessage("account.name", null, Locale.ENGLISH);

Spring also provides the ReloadableResourceBundleMessageSource class, which allows for reading files from any Spring resource location and supports hot reloading of bundle property files.

6.2. Event Handling

ApplicationContext supports event handling with the help of the ApplicationEvent class and the ApplicationListener interface. It supports built-in events like ContextStartedEvent, ContextStoppedEvent, ContextClosedEvent, and RequestHandledEvent. Moreover, it also supports custom events for business use cases.

7. Conclusion

In this tutorial, we've discussed various aspects of the ApplicationContext container in Spring. We've seen different examples of how to configure Spring beans in an AppicationContext. Also, we've seen how to create and use different types of ApplicationContext.

Як завжди, повний код доступний на GitHub.