1. Обзор
Проще говоря, ядро Spring Framework - это контейнер IoC, используемый для управления bean-компонентами.
В Spring есть два основных типа контейнеров - Bean Factory и Application Context. Первый обеспечивает основные функциональные возможности, которые вводятся по ссылке:/spring-beanfactory[здесь]; последний является надмножеством первого и наиболее широко используется.
ApplicationContext - это интерфейс в пакете org.springframework.context , он имеет несколько реализаций, и ClassPathXmlApplicationContext является одним из них.
В этой статье мы сосредоточимся на полезных функциях, предоставляемых ClassPathXmlApplicationContext .
2. Основное использование
2.1. Инициализация контейнера и управление компонентами
ClassPathXmlApplicationContext может загрузить конфигурацию XML из пути к классам и управлять его bean-компонентами:
У нас есть класс Student :
public class Student {
private int no;
private String name;
//standard constructors, getters and setters
}
Мы настраиваем bean-компонент Student в classpathxmlapplicationcontext-example.xml и добавляем его в путь к классам:
<beans ...>
<bean id="student" class="com.baeldung.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 в веб-приложении, веб-реализации ApplicationContext в Spring будут корректно завершать работу контейнера при завершении работы приложения, но если мы используем его в не-веб-среде, например в автономном настольном приложении, Мы должны самостоятельно зарегистрировать перехватчик в JVM, чтобы убедиться, что контейнер Spring IoC корректно завершил работу и вызывает методы destroy для освобождения ресурсов.
Давайте добавим метод destroy () в класс Student :
public void destroy() {
System.out.println("Student(no: " + no + ") is destroyed");
}
Теперь мы можем настроить этот метод как метод уничтожения бина student :
<beans ...>
<bean id="student" class="com.baeldung.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 в путь к классам и добавим два файла в каталог диалогов: 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 :
У нас есть класс Course с именем:
public class Course {
private String name;
//standard constructors, getters and setters
}
У нас есть класс Teacher , который собирает свои курсы согласно бинам контейнера:
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-компонент course и bean-компонент teacher в classpathxmlapplicationcontext-example.xml :
<beans ...>
<bean id="math" class="com.baeldung.applicationcontext.Course">
<property name="name" value="math"/>
</bean>
<bean name="teacher" class="com.baeldung.applicationcontext.Teacher"/>
</beans>
Затем - протестируйте внедрение свойства courses :
@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 имеет тот же эффект.
Давайте изменим класс Teacher на этот:
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 https://github.com/eugenp/tutorials/tree/master/spring-core/src/test/java/com/baeldung/applicationcontext/ [over на GitHub.