????? 到目前為止,我們都是使用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("");
??? }
}