Spring学习笔记(七)-----Spring in Action
解析文本信息:
有时,你不希望硬编码显示给用户信息。也许是因为这个信息经常发生改变,或者是你的应用系统提供国际化功能,你要用用户的本地语言显示文本。
java对文本国际化的支持使你能够定义一个或多个属性文件保存应用系统中需要显示的文本。Spring的ApplicationContext通过MessageSource接口为容器提供参数化信息支持,Spring提供了一个现成的MessageSource实现。ResourceBundleMessageSource只是调用java自己的java.util.ResourceBundle来解析信息。
例如:
<
bean
id
="messageSource"
class
="org.springframework.context.support.ResourceBundleMessageSource"
>
< property name ="basename" >
< value > trainingtext </ value >
</ property >
</ bean >
< property name ="basename" >
< value > trainingtext </ value >
</ property >
</ bean >
这个Bean的名字必须是messageSource,因为ApplicationContext在装配应用系统Bean的时候查找这个名字的Bean,你不需要将messageSource注入到应用系统中的Bean中,而是使用ApplicationContext自己的getMessage()方法。
Locale locale = ...;
第一个参数表示文本文件中的ID
第二个参数表示传递到资源文件中的数组,显示最终文件
第三个参数表示采用哪种方式显示
String text = context.getMessage("computer",new Object[0],locale);
监听事件与发布事件:
如果你想对一个类的方法进行监听,首先要定义事件,然后在这个方法中通过ApplicationContext发布它,最后在ApplicationContext.xml中定义这个监听器。这样,每当方法执行的时候,监听器就会监听到对应的事件的触发。
事件分为ApplicationContext发布的事件和自定义的事件。这些事件都是抽象类org.springframework.context.ApplicationEvent的子类。
在应用系统生命周期中,ApplicationContext会发布很多事件,告诉感兴趣的监听器发生了什么事情。。系统事件有如下几个:
1、ContextClosedEvent:在应用上下文关闭的时候发布的事件;
2、contextRefreshedEvent:在应用上下文初始化或刷新的时候发布的事件;
3、RequestHandledEvent:在web应用上下文中,当一个请求被处理后发布的事件。
首先要编写为哪个类的哪个方法添加事件:
public
class
Animal
implements
ApplicationContextAware {
private ApplicationContext ac;
private String name;
private int age;
public String speak(){
ac.publishEvent( new AnimalSpeakEvent( this , this .name));
return " 我的名字是; " + this .name + " ,我的年龄是: " + this .age;
}
public void setApplicationContext(ApplicationContext arg0) throws BeansException {
this .ac = arg0;
}
// Getet和Seter省略
}
private ApplicationContext ac;
private String name;
private int age;
public String speak(){
ac.publishEvent( new AnimalSpeakEvent( this , this .name));
return " 我的名字是; " + this .name + " ,我的年龄是: " + this .age;
}
public void setApplicationContext(ApplicationContext arg0) throws BeansException {
this .ac = arg0;
}
// Getet和Seter省略
}
自定义事件入下:
import
org.springframework.context.ApplicationEvent;
public class AnimalSpeakEvent extends ApplicationEvent {
private static final long serialVersionUID = 1L ;
private String animalName;
public AnimalSpeakEvent(Object source) {
super (source);
}
public AnimalSpeakEvent(Object source,String animalName) {
super (source);
this .animalName = animalName;
}
public String getAnimalName() {
return animalName;
}
}
public class AnimalSpeakEvent extends ApplicationEvent {
private static final long serialVersionUID = 1L ;
private String animalName;
public AnimalSpeakEvent(Object source) {
super (source);
}
public AnimalSpeakEvent(Object source,String animalName) {
super (source);
this .animalName = animalName;
}
public String getAnimalName() {
return animalName;
}
}
然后是实现监听器,监听器必须实现org.springframework.context.ApplicationListener接口。这个接口要求你的Bean实现onApplicationEvent()方法:
public
class
RefreshListener
implements
ApplicationListener{
public void onApplicationEvent(ApplicationEvent event){
}
}
public void onApplicationEvent(ApplicationEvent event){
}
}
import
org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
public class AnimalEventListener implements ApplicationListener {
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof AnimalSpeakEvent) {
AnimalSpeakEvent a = (AnimalSpeakEvent) event;
System.out.println( " 事件监听器 " + this .getClass().getSimpleName() + " :有一个动物在讲话!它的名字是: " + a.getAnimalName());
}
}
}
import org.springframework.context.ApplicationListener;
public class AnimalEventListener implements ApplicationListener {
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof AnimalSpeakEvent) {
AnimalSpeakEvent a = (AnimalSpeakEvent) event;
System.out.println( " 事件监听器 " + this .getClass().getSimpleName() + " :有一个动物在讲话!它的名字是: " + a.getAnimalName());
}
}
}
最后就是在映射文件中定义这个监听器:
<?
xml version
=
"
1.0
"
encoding
=
"
UTF-8
"
?>
< beans ………… >
< bean id = " Listener " class = " ioc.test.AnimalEventListener " />
< bean id = " Animal " class = " ioc.test.Animal " >
< property name = " name " value = " 老虎 " />
< property name = " age " value = " 5 " />
</ bean >
</ beans >
最后是测试类:
< beans ………… >
< bean id = " Listener " class = " ioc.test.AnimalEventListener " />
< bean id = " Animal " class = " ioc.test.Animal " >
< property name = " name " value = " 老虎 " />
< property name = " age " value = " 5 " />
</ bean >
</ beans >
import
org.springframework.context.support.AbstractApplicationContext;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestMain {
public static void main(String[] args) {
AbstractApplicationContext ac = new ClassPathXmlApplicationContext(
" applicationContext.xml " );
// 从容器获取动物实例
Animal animal = (Animal)ac.getBean( " Animal " );
// 让动物讲话
System.out.println(animal.speak());
}
}
public class TestMain {
public static void main(String[] args) {
AbstractApplicationContext ac = new ClassPathXmlApplicationContext(
" applicationContext.xml " );
// 从容器获取动物实例
Animal animal = (Animal)ac.getBean( " Animal " );
// 让动物讲话
System.out.println(animal.speak());
}
}
感知其他Bean:
在极大程度上,运行在Spring容器中的Bean就像生活在The Matrix里的人类。对于这些Bean来说,他们不知道自己的注册名,甚至不知道自己运行在容器中。通常这是好事,因为如果一个Bean知道容器的存在的话,他就和Spring耦合在一起了,在容器以外无法存在。
但有时候Bean需要知道更多信息。有时他们需要知道他们是谁,他们在哪里运行。有时他们需要服用那颗红色药丸。
在Spring Bean环境中,红色药丸就是BeanNameAware、BeanFactoryAware和ApplicationContextAware接口。通过实现这3个接口,Bean分别可以知道自己的名字,他们所处的BeanFactory以及他们所处的ApplicationContext.
注意,通过实现这些接口,一个Bean就和Spring耦合在一起。
感知系统容器对于Bean来说是福是祸。一方面,应用上下文的获得给Bean提供了很多权利。另一方面,知道容器会把Bean和Spring耦合起来,这是要尽量避免的事情。