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类:
public
class
Student
{
-
private
int no;
-
private
String name;
-
// standard constructors, getters and setters
}
我们在classpathxmlapplicationcontext-example.xml中配置Student bean并将其添加到类路径中:
<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的ApplicationContext实现将在关闭应用程序时正常关闭容器,但如果我们在非Web环境中使用它,
例如独立的桌面应用程序,我们我们必须自己向JVM注册一个关闭钩子,以确保Spring IoC容器正常关闭并调用destroy方法释放资源。
在Student类中添加一个destroy()方法:
public
void destroy()
{
-
System.out.println("Student(no: "
no
") is destroyed");
}
我们现在可以将此方法配置为student bean的destroy方法:
<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容器在其初始化时自动搜索MessageSource bean,并且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}
在classpathxmlapplicationcontext-internationalization.xml中配置messageSource bean:
<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:
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
}
在classpathxmlapplicationcontext-example.xml中配置课程bean和教师bean:
<beans ...>
-
<bean id="math"
class="com.baeldung.applicationcontext.Course">
-
<property name="name" value="math"/>
-
</bean>
-
<bean name="teacher"
class="com.baeldung.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注释也具有相同的效果。
将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
}
然后运行测试用例,我们可以看到结果是一样的。
总结
ApplicationContext是一个Spring容器,与BeanFactory相比具有更多特定于企业应用的功能,而ClassPathXmlApplicationContext是其最常用的实现之一。
因此,在本文中,我们介绍了ClassPathXmlApplicationContext的几个方面,包括其基本用法,关闭注册功能,国际化功能以及获取其引用。