Spring之ClassPathXmlApplicationContext

2020-11-19 17:42:08 浏览数 (1)

Spring之ClassPathXmlApplicationContext

听说转发文章

会给你带来好运

1

介绍

简单地说,Spring Framework核心是一个用于管理bean的IoC容器。

Spring中有两种基本类型的容器 - Bean Factory和Application Context。 前者提供了基本功能,在此介绍; 后者是前者的超集,是最广泛使用的。

ApplicationContext是org.springframework.context包中的一个接口,它有几个实现,ClassPathXmlApplicationContext就是其中之一。

在本文中,我们将重点介绍ClassPathXmlApplicationContext提供的有用功能。

2

基本用法

2.1 初始化容器和管理Bean

ClassPathXmlApplicationContext可以从类路径加载XML配置并管理其bean。

我们有一个Student类:

  1. public class Student {
  2. private int no;
  3. private String name;
  4. // standard constructors, getters and setters
  5. }

我们在classpathxmlapplicationcontext-example.xml中配置Student bean并将其添加到类路径中:

  1. <beans ...>
  2. <bean id="student" class="com.baeldung.applicationcontext.Student">
  3. <property name="no" value="15"/>
  4. <property name="name" value="Tom"/>
  5. </bean>
  6. </beans>

现在我们可以使用ClassPathXmlApplicationContext来加载XML配置并获取Student bean:

  1. @Test
  2. public void testBasicUsage() {
  3. ApplicationContext context
  4. = new ClassPathXmlApplicationContext(
  5. "classpathxmlapplicationcontext-example.xml");
  6. Student student = (Student) context.getBean("student");
  7. assertThat(student.getNo(), equalTo(15));
  8. assertThat(student.getName(), equalTo("Tom"));
  9. Student sameStudent = context.getBean("student", Student.class);
  10. assertThat(sameStudent.getNo(), equalTo(15));
  11. assertThat(sameStudent.getName(), equalTo("Tom"));
  12. }

2.2 多个XML配置

有时我们想使用几个XML配置来初始化Spring容器。 在这种情况下,我们只需要在构造ApplicationContext时添加几个配置位置:

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

3

附加功能

3.1 优雅关闭Spring IOC容器

当我们在Web应用程序中使用Spring IoC容器时,Spring的基于Web的ApplicationContext实现将在关闭应用程序时正常关闭容器,但如果我们在非Web环境中使用它,

例如独立的桌面应用程序,我们我们必须自己向JVM注册一个关闭钩子,以确保Spring IoC容器正常关闭并调用destroy方法释放资源。

在Student类中添加一个destroy()方法:

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

我们现在可以将此方法配置为student bean的destroy方法:

  1. <beans ...>
  2. <bean id="student" class="com.baeldung.applicationcontext.Student"
  3. destroy-method="destroy">
  4. <property name="no" value="15"/>
  5. <property name="name" value="Tom"/>
  6. </bean>
  7. </beans>

我们现在将注册一个关闭钩子:

  1. @Test
  2. public void testRegisterShutdownHook() {
  3. ConfigurableApplicationContext context
  4. = new ClassPathXmlApplicationContext(
  5. "classpathxmlapplicationcontext-example.xml");
  6. context.registerShutdownHook();
  7. }

当我们运行测试方法时,我们可以看到调用destroy()方法。

3.2 使用MessageSource进行国际化

ApplicationContext接口扩展了MessageSource接口,因此提供了国际化功能。

ApplicationContext容器在其初始化时自动搜索MessageSource bean,并且bean必须命名为messageSource。

以下是使用MessageSource使用不同语言的示例。

首先,让我们将一个会话目录添加到类路径中,并将两个文件添加到会话目录中:dialog_en.properties和dialog_zh_CN.properties。

dialog_en.properties:

  1. hello=hello
  2. you=you
  3. thanks=thank {0}

dialog_zh_CN.properties:

  1. hello=\u4f60\u597d
  2. you=\u4f60
  3. thanks=\u8c22\u8c22{0}

在classpathxmlapplicationcontext-internationalization.xml中配置messageSource bean:

  1. <beans ...>
  2. <bean id="messageSource"
  3. class="org.springframework.context.support.ResourceBundleMessageSource">
  4. <property name="basenames">
  5. <list>
  6. <value>dialog/dialog</value>
  7. </list>
  8. </property>
  9. </bean>
  10. </beans>

然后,让我们使用MessageSource获取不同语言的对话框:

  1. @Test
  2. public void testInternationalization() {
  3. MessageSource resources
  4. = new ClassPathXmlApplicationContext(
  5. "classpathxmlapplicationcontext-internationalization.xml");
  6. String enHello = resources.getMessage(
  7. "hello", null, "Default", Locale.ENGLISH);
  8. String enYou = resources.getMessage(
  9. "you", null, Locale.ENGLISH);
  10. String enThanks = resources.getMessage(
  11. "thanks", new Object[] { enYou }, Locale.ENGLISH);
  12. assertThat(enHello, equalTo("hello"));
  13. assertThat(enThanks, equalTo("thank you"));
  14. String chHello = resources.getMessage(
  15. "hello", null, "Default", Locale.SIMPLIFIED_CHINESE);
  16. String chYou = resources.getMessage(
  17. "you", null, Locale.SIMPLIFIED_CHINESE);
  18. String chThanks = resources.getMessage(
  19. "thanks", new Object[] { chYou }, Locale.SIMPLIFIED_CHINESE);
  20. assertThat(chHello, equalTo("你好"));
  21. assertThat(chThanks, equalTo("谢谢你"));
  22. }

4

ApplicationContext引用

有时我们需要在由它管理的bean中获取ApplicationContext的引用,我们可以使用ApplicationContextAware或@Autowired来执行此操作。

让我们看看如何使用ApplicationContextAware:

  1. public class Course {
  2. private String name;
  3. // standard constructors, getters and setters
  4. }

我们有一个Teacher类,它根据容器的bean组装它的课程:

  1. public class Teacher implements ApplicationContextAware {
  2. private ApplicationContext context;
  3. private List<Course> courses = new ArrayList<>();
  4. @Override
  5. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  6. this.context = applicationContext;
  7. }
  8. @PostConstruct
  9. public void addCourse() {
  10. if (context.containsBean("math")) {
  11. Course math = context.getBean("math", Course.class);
  12. courses.add(math);
  13. }
  14. if (context.containsBean("physics")) {
  15. Course physics = context.getBean("physics", Course.class);
  16. courses.add(physics);
  17. }
  18. }
  19. // standard constructors, getters and setters
  20. }

在classpathxmlapplicationcontext-example.xml中配置课程bean和教师bean:

  1. <beans ...>
  2. <bean id="math" class="com.baeldung.applicationcontext.Course">
  3. <property name="name" value="math"/>
  4. </bean>
  5. <bean name="teacher" class="com.baeldung.applicationcontext.Teacher"/>
  6. </beans>

然后,测试课程属性的注入:

  1. @Test
  2. public void testApplicationContextAware() {
  3. ApplicationContext context
  4. = new ClassPathXmlApplicationContext(
  5. "classpathxmlapplicationcontext-example.xml");
  6. Teacher teacher = context.getBean("teacher", Teacher.class);
  7. List<Course> courses = teacher.getCourses();
  8. assertThat(courses.size(), equalTo(1));
  9. assertThat(courses.get(0).getName(), equalTo("math"));
  10. }

除了实现ApplicationContextAware接口之外,使用@Autowired注释也具有相同的效果。

将Teacher类更改为:

  1. public class Teacher {
  2. @Autowired
  3. private ApplicationContext context;
  4. private List<Course> courses = new ArrayList<>();
  5. @PostConstruct
  6. public void addCourse() {
  7. if (context.containsBean("math")) {
  8. Course math = context.getBean("math", Course.class);
  9. courses.add(math);
  10. }
  11. if (context.containsBean("physics")) {
  12. Course physics = context.getBean("physics", Course.class);
  13. courses.add(physics);
  14. }
  15. }
  16. // standard constructors, getters and setters
  17. }

然后运行测试用例,我们可以看到结果是一样的。

总结

ApplicationContext是一个Spring容器,与BeanFactory相比具有更多特定于企业应用的功能,而ClassPathXmlApplicationContext是其最常用的实现之一。

因此,在本文中,我们介绍了ClassPathXmlApplicationContext的几个方面,包括其基本用法,关闭注册功能,国际化功能以及获取其引用。

0 人点赞