Перейти к основному содержимому

Введение в Spring ClassPathXmlApplicationContext

· 5 мин. чтения

1. Обзор

Проще говоря, ядро Spring Framework — это контейнер IoC, используемый для управления bean-компонентами.

В Spring есть два основных типа контейнеров — Bean Factory и Application Context. Первый предоставляет базовые функции, которые представлены здесь ; последний является надмножеством первого и наиболее широко используется.

ApplicationContext — это интерфейс в пакете org.springframework.context , который имеет несколько реализаций, и ClassPathXmlApplicationContext — одна из них.

В этой статье мы сосредоточимся на полезных функциях, предоставляемых ClassPathXmlApplicationContext .

2. Основное использование

2.1. Инициализировать контейнер и управлять компонентами

ClassPathXmlApplicationContext может загружать конфигурацию XML из пути к классам и управлять его компонентами:

У нас есть студенческий класс:

public class Student {
private int no;
private String name;

// standard constructors, getters and setters
}

Мы настраиваем компонент Student в classpathxmlapplicationcontext-example.xml и добавляем его в путь к классам:

<beans ...>
<bean id="student" class="com.foreach.applicationcontext.Student">
<property name="no" value="15"/>
<property name="name" value="Tom"/>
</bean>
</beans>

Теперь мы можем использовать ClassPathXmlApplicationContext для загрузки конфигурации XML и получения bean- компонента Student :

@Test
public void testBasicUsage() {
ApplicationContext context
= new ClassPathXmlApplicationContext(
"classpathxmlapplicationcontext-example.xml");

Student student = (Student) context.getBean("student");
assertThat(student.getNo(), equalTo(15));
assertThat(student.getName(), equalTo("Tom"));

Student sameStudent = context.getBean("student", Student.class);
assertThat(sameStudent.getNo(), equalTo(15));
assertThat(sameStudent.getName(), equalTo("Tom"));
}

2.2. Несколько конфигураций XML

Иногда мы хотим использовать несколько конфигураций XML для инициализации контейнера Spring. В этом случае нам просто нужно добавить несколько мест конфигурации при создании ApplicationContext :

ApplicationContext context 
= new ClassPathXmlApplicationContext("ctx.xml", "ctx2.xml");

3. Дополнительные возможности

3.1. Изящно завершите работу контейнера Spring IoC

Когда мы используем контейнер Spring IoC в веб-приложении, веб- реализации Spring ApplicationContext корректно завершат работу контейнера при закрытии приложения, но если мы используем его в не-веб-среде, например, в автономном настольном приложении, мы должны самостоятельно зарегистрировать обработчик завершения работы с JVM, чтобы убедиться, что контейнер Spring IoC корректно закрыт, и вызывает методы уничтожения для освобождения ресурсов.

Давайте добавим метод destroy() в класс Student :

public void destroy() {
System.out.println("Student(no: " + no + ") is destroyed");
}

Теперь мы можем настроить этот метод как метод уничтожения бина - ученика :

<beans ...>
<bean id="student" class="com.foreach.applicationcontext.Student"
destroy-method="destroy">
<property name="no" value="15"/>
<property name="name" value="Tom"/>
</bean>
</beans>

Теперь мы зарегистрируем хук выключения:

@Test
public void testRegisterShutdownHook() {
ConfigurableApplicationContext context
= new ClassPathXmlApplicationContext(
"classpathxmlapplicationcontext-example.xml");
context.registerShutdownHook();
}

Когда мы запускаем тестовый метод, мы видим, что вызывается метод destroy() .

3.2. Интернационализация с MessageSource

Интерфейс ApplicationContext расширяет интерфейс MessageSource , поэтому обеспечивает функциональность интернационализации.

Контейнер ApplicationContext автоматически ищет bean-компонент MessageSource при своей инициализации, и этот bean-компонент должен быть назван messageSource .

Вот пример использования разных языков с MessageSource :

Во-первых, давайте добавим каталог диалога в путь к классам и добавим в каталог диалога два файла: dialog_en.properties и dialog_zh_CN.properties .

dialog_en.properties :

hello=hello
you=you
thanks=thank {0}

dialog_zh_CN.properties :

hello=\u4f60\u597d
you=\u4f60
thanks=\u8c22\u8c22{0}

Настройте bean-компонент messageSource в classpathxmlapplicationcontext-internationalization.xml :

<beans ...>
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>dialog/dialog</value>
</list>
</property>
</bean>
</beans>

Затем давайте получим диалоговые слова разных языков с помощью MessageSource :

@Test
public void testInternationalization() {
MessageSource resources
= new ClassPathXmlApplicationContext(
"classpathxmlapplicationcontext-internationalization.xml");

String enHello = resources.getMessage(
"hello", null, "Default", Locale.ENGLISH);
String enYou = resources.getMessage(
"you", null, Locale.ENGLISH);
String enThanks = resources.getMessage(
"thanks", new Object[] { enYou }, Locale.ENGLISH);

assertThat(enHello, equalTo("hello"));
assertThat(enThanks, equalTo("thank you"));

String chHello = resources.getMessage(
"hello", null, "Default", Locale.SIMPLIFIED_CHINESE);
String chYou = resources.getMessage(
"you", null, Locale.SIMPLIFIED_CHINESE);
String chThanks = resources.getMessage(
"thanks", new Object[] { chYou }, Locale.SIMPLIFIED_CHINESE);

assertThat(chHello, equalTo("你好"));
assertThat(chThanks, equalTo("谢谢你"));
}

4. Ссылка на ApplicationContext

Иногда нам нужно получить ссылку на ApplicationContext внутри управляемых им bean-компонентов, для этого мы можем использовать ApplicationContextAware или @Autowired . Давайте посмотрим, как работает ApplicationContextAware :

У нас есть класс курса с именем:

public class Course {

private String name;

// standard constructors, getters and setters
}

У нас есть класс учителя , который собирает свои курсы в соответствии с компонентами контейнера:

public class Teacher implements ApplicationContextAware {

private ApplicationContext context;
private List<Course> courses = new ArrayList<>();

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}

@PostConstruct
public void addCourse() {
if (context.containsBean("math")) {
Course math = context.getBean("math", Course.class);
courses.add(math);
}
if (context.containsBean("physics")) {
Course physics = context.getBean("physics", Course.class);
courses.add(physics);
}
}

// standard constructors, getters and setters
}

Давайте настроим bean-компоненты курса и bean-компонента учителя в classpathxmlapplicationcontext-example.xml :

<beans ...>
<bean id="math" class="com.foreach.applicationcontext.Course">
<property name="name" value="math"/>
</bean>

<bean name="teacher" class="com.foreach.applicationcontext.Teacher"/>
</beans>

Затем — протестируйте инъекцию свойства курсов :

@Test
public void testApplicationContextAware() {
ApplicationContext context
= new ClassPathXmlApplicationContext(
"classpathxmlapplicationcontext-example.xml");
Teacher teacher = context.getBean("teacher", Teacher.class);
List<Course> courses = teacher.getCourses();

assertThat(courses.size(), equalTo(1));
assertThat(courses.get(0).getName(), equalTo("math"));
}

Помимо реализации интерфейса ApplicationContextAware , такой же эффект дает использование аннотации @Autowired .

Давайте изменим класс учителя на это:

public class Teacher {

@Autowired
private ApplicationContext context;
private List<Course> courses = new ArrayList<>();

@PostConstruct
public void addCourse() {
if (context.containsBean("math")) {
Course math = context.getBean("math", Course.class);
courses.add(math);
}
if (context.containsBean("physics")) {
Course physics = context.getBean("physics", Course.class);
courses.add(physics);
}
}

// standard constructors, getters and setters
}

Затем запустите этот тест, мы увидим, что результат тот же.

5. Вывод

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

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

Как всегда, полный исходный код примера доступен на GitHub .