到目前为止,我们都是使用BeanFactory接口以及它的子接口来使用Spring,尽管使用BeanFactory也是一种不错的方式,但正如前面看到的,有些时候,我们还是不得不自己编写代码来调用诸如preInstantiateSingletons,postProcessBeanFactory等方法。
为了使用的方便,Spring提供了BeanFactory的一个扩展:ApplicationContext。使用ApplicationContext,我们可以减少需要编写的代码的数量,并且ApplicationContext也增加了一些新的功能。如果在Web工程中使用Spring,我们甚至可以让Spring自动加载ApplicationContext,而无需自己编写代码来创建它。
ApplicationContext具备一些BeanFactory不具备的功能:国际化(Internationalization),事件发布(Event publication),资源管理和访问(Resource management and access),更多的生命周期控制接口(Additional lifecycle interfaces)以及底层组件的自动配置(Improved automatic configuration of infrastructure components)。
Spring为ApplicationContext接口提供了三种实现:FileSystemXmlApplicationContext,ClasspathXmlApplicationContext和XmlWebApplicationContext。其中XmlWebApplicationContext是专为Web工程定制的,并且我们可以使用ContextLoaderListener或ContextLoaderServlet来自动加载ApplicationContext配置。
通常国际化是通过使用MessageSource接口来实现的,为了在ApplicationContext中使用MessageSource,我们需要配置一个类型为MessageSource,名称为messageSource的bean。
<beans> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basenames"> <list> <value>buttons</value> <value>labels</value> </list> </property> </bean> </beans>
在配置了messageSource后,我们就可以使用ApplicationContext的getMessage方法来获取资源内容了。
ApplicationContext的另一个重要特性就是对发布和接收事件的支持,ApplicationContext会在其被配置的时候自动注册所有的侦听器(listener),事件的发布是通过ApplicationContext的publishEvent方法来实现的。
//Event class
public class MessageEvent extends ApplicationEvent { private String msg; public MessageEvent(Object source, String msg) { super(source); this.msg = msg; } public String getMessage() { return msg; } }
//Listener class
public class MessageEventListener implements ApplicationListener { public void onApplicationEvent(ApplicationEvent event) { if(event instanceof MessageEvent) { MessageEvent msgEvt = (MessageEvent)event; System.out.println("Received: " + msgEvt.getMessage()); } } }
//Publish class
public class Publisher implements ApplicationContextAware { private ApplicationContext ctx; public static void main(String[] args) { ApplicationContext ctx =
new FileSystemXmlApplicationContext("./ch5/src/conf/events/events.xml"); Publisher pub = (Publisher) ctx.getBean("publisher"); pub.publish("Hello World!"); pub.publish("The quick brown fox jumped over the lazy dog"); } public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException { this.ctx = applicationContext; } public void publish(String message) { ctx.publishEvent(new MessageEvent(this, message)); } }
<beans> <bean id="publisher" class="com.apress.prospring.ch5.event.Publisher"/> <bean id="messageEventListener" class="com.apress.prospring.ch5.event.MessageEventListener"/> </beans>
资源访问是我们经常碰到的,这些资源有可能存在于一个文件中,类路径中的一个jar包中,抑或是在远程服务器上。Spring为我们提供了统一的,协议无关的方式来访问各种各样的资源,这给我们访问各种资源提供了极大的方便。
public class ResourceDemo { public static void main(String[] args) throws Exception { ApplicationContext ctx =
new FileSystemXmlApplicationContext("./ch5/src/conf/events/events.xml"); Resource res1 = ctx.getResource("file:///d:/tmp/test.txt"); displayInfo(res1); Resource res2 = ctx.getResource("classpath:lib/commons-logging.jar"); displayInfo(res2); Resource res3 = ctx.getResource("http://www.google.co.uk"); displayInfo(res3); } private static void displayInfo(Resource res) throws Exception { System.out.println(res.getClass()); System.out.println(res.getURL().getContent()); System.out.println(""); } }
|
|