1. 概述
Spring 框架的核心,簡單來説,是一個 IoC 容器,用於管理 Bean。
在 Spring 中,有兩種基本類型的容器:Bean 工廠和 Application Context。前者提供基本功能,此處將介紹;後者是前者的超集,並且被廣泛使用。
ApplicationContext 是 org.springframework.context 包中的一個接口,並且它有多個實現,其中 ClassPathXmlApplicationContext 就是其中之一。
在本文中,我們將重點介紹 ClassPathXmlApplicationContext 提供的有用功能。
2. 基本用法
This section covers the basic usage of the library.
Installation
To install the library, use the following command:
npm install your-library-name
Getting Started
- Import the library into your project.
- Create an instance of the library.
- Call the library's methods to perform operations.
Example
// Import the library
const yourLibrary = require('your-library-name');
// Create an instance
const instance = new yourLibrary();
// Call a method
const result = instance.doSomething('some input');
console.log(result);
Common Methods
doSomething(input): Performs a specific operation.anotherMethod(param1, param2): Another useful function.reset(): Resets the library to its initial state.
2.1. 初始化容器和管理 Bean
<em classPathXmlApplicationContext</em> 可以從 classpath 加載 XML 配置文件並管理其中的 Bean:
我們有一個 <em Student</em> 類:
public class Student {
private int no;
private String name;
// standard constructors, getters and setters
}我們配置了一個 Student Bean 在 classpathxmlapplicationcontext-example.xml 中,並將其添加到 classpath 中:
<beans ...>
<bean id="student" class="com.baeldung.applicationcontext.Student">
<property name="no" value="15"/>
<property name="name" value="Tom"/>
</bean>
</beans>現在我們可以使用 ClassPathXmlApplicationContext 類加載 XML 配置文件並獲取 Student Bean:
@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 容器
當我們在 Web 應用程序中使用 Spring IoC 容器時,Spring 的基於 Web 的 <em >ApplicationContext</em> 實現會在應用程序關閉時優雅地關閉容器。但是,如果我們在非 Web 環境中使用它,例如獨立桌面應用程序,則必須手動向 JVM 註冊一個 shutdown hook,以確保 Spring IoC 容器以優雅的方式關閉並調用 destroy 方法以釋放資源。
讓我們為 <em >Student</em> 類添加一個 <em >destroy()</em> 方法:
public void destroy() {
System.out.println("Student(no: " + no + ") is destroyed");
}我們現在可以將此方法配置為 student bean 的銷燬方法:
<beans ...>
<bean id="student" class="com.baeldung.applicationcontext.Student"
destroy-method="destroy">
<property name="no" value="15"/>
<property name="name" value="Tom"/>
</bean>
</beans>我們現在將註冊一個 shutdown hook:
@Test
public void testRegisterShutdownHook() {
ConfigurableApplicationContext context
= new ClassPathXmlApplicationContext(
"classpathxmlapplicationcontext-example.xml");
context.registerShutdownHook();
}當我們運行測試方法時,我們可以看到 destroy() 方法被調用。
3.2. 使用 MessageSource 進行國際化
<em >ApplicationContext</em > 接口繼承了 <em >MessageSource</em > 接口,因此提供國際化功能。
<em >ApplicationContext</em > 容器會在初始化時自動搜索 <em >MessageSource</em > 類型的 Bean,並且該 Bean 的名稱必須為 <em >messageSource</em >。
以下是一個使用 <em >MessageSource</em > 實現不同語言的示例:
首先,將 <em >dialog</em > 目錄添加到 Classpath 中,並在該目錄下添加兩個文件:<em >dialog_en.properties</em > 和 <em >dialog_zh_CN.properties</em >。
<em >dialog_en.properties</em >:
hello=hello
you=you
thanks=thank {0}dialog_zh_CN.properties:
hello=\u4f60\u597d
you=\u4f60
thanks=\u8c22\u8c22{0}配置 messageSource Bean 在 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 的引用
有時我們需要在由它管理 Bean 內部獲取 ApplicationContext 的引用,可以使用 ApplicationContextAware 或 @Autowired 來實現。 讓我們看看如何使用 ApplicationContextAware:
我們有一個 Course 類,其中包含一個名稱:
public class Course {
private String name;
// standard constructors, getters and setters
}我們有一個 Teacher 類,它根據容器中的 Bean 組裝課程:
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
}讓我們配置 course Bean 和 teacher Bean 在 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. 結論
<em>ApplicationContext</em> 是一個比 <em>BeanFactory</em> 更具有企業級功能的 Spring 容器,<em>ClassPathXmlApplicationContext</em> 是其最常用的實現之一。
因此,在本文中,我們介紹了 <em>ClassPathXmlApplicationContext</em> 的幾個方面,包括其基本用法、其 shutdown 註冊功能、其國際化功能以及獲取其引用。