1. 程式人生 > >Spring進階之路(2)-ApplicationContext容器以及事件機制

Spring進階之路(2)-ApplicationContext容器以及事件機制

Spring容器最基本的介面是BeanFactory,他負責配置、建立、管理bean,他的子介面之一:ApplicationContext,也叫做spring的上下文。ApplicationContext是BeanFactory的子介面,在web應用中,通常會用到XmlWebApplicationContext、AnnotationCofigWebApplicationContext兩個實現類。

ApplicationContext簡介

系統建立ApplicationContext容器的時候,預設會預先初始化所有的單例的bean,呼叫構造器建立例項物件,然後通過set方法注入依賴的物件例項。這樣的情況下,也就是說會面臨著一個問題,容器在初始化的時候會有較大的效能的消耗,但是一旦初始化完成之後,程式在獲取單例的bean的時候,又會獲得較好的效能。

下面看一個簡單的例子,來理解一下ApplicationContext的初始化流程。

建立如下的一個類。包括無引數的建構函式以及一個set方法。

package com.siti.spring20160228;

public class WangYang {

	public WangYang(){
		System.out.println("無參的建構函式!");
	}
	
	public void setName(String name){
		System.out.println("my name is " + name);
	}
}
配置檔案中新增這個bean類。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- bean definitions here -->
	<bean id = "wy" class = "com.siti.spring20160228.WangYang">
		<property name="name" value="wy"></property>
	</bean>
</beans>

測試類,只建立一個ApplicationContext的例項物件。
package com.siti.spring20160228;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainTest {

	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext20160228.xml");
	}
}

測試結果:



ApplicationContext的事件機制

ApplicationContext的事件機制屬於觀察者設計模式(設計模式篇會在後期專門推出請讀者關注),通過ApplicationEvent和ApplicationListener介面,可以實現ApplicationContext的事件處理。

spring事件機制中ApplicationEvent和ApplicationListener起到重要作用。其中,ApplicationEvent:由ApplicationContext釋出。ApplicationListener可以由容器裡面任何的監聽器bean擔任。


下面以一段例項進行講解

MessageEvent類繼承了ApplicationEvent類,一個事件。

package com.siti.spring20160228.applicationContextListener;

import org.springframework.context.ApplicationEvent;

public class MessageEvent extends ApplicationEvent {
	private static final long serialVersionUID = 1L;

	private String messageContent;
	
	public MessageEvent(Object source) {
		super(source);
	}
	
	public MessageEvent(Object source, String messageContent) {
		super(source);
		this.messageContent = messageContent;
	}

	public String getMessageContent() {
		return messageContent;
	}

	public void setMessageContent(String messageContent) {
		this.messageContent = messageContent;
	}
	
	
}
監聽器類實現ApplicationListener介面實現需要實現的這個方法,發生事件的時候會被觸發。
package com.siti.spring20160228.applicationContextListener;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;

public class MessageListener implements ApplicationListener<ApplicationEvent> {

	// 容器事件發生的時候觸發方法的執行
	@Override
	public void onApplicationEvent(ApplicationEvent event) {
		if(event instanceof MessageEvent){
			MessageEvent messageEvent = (MessageEvent) event;
			System.out.println("資訊內容是:" + messageEvent.getMessageContent());
		}else{
			System.out.println("其他的資訊!" + event.toString());
		}
		
	}

}

註冊監聽器,在spring的配置檔案當中配置一下即可。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- bean definitions here -->
	
	<bean class = "com.siti.spring20160228.applicationContextListener.MessageListener"></bean>
	
</beans>

在測試程式中進行測試如下:
package com.siti.spring20160228.applicationContextListener;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainTest {

	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext20160228.xml");
		
		MessageEvent event = new MessageEvent("", "my name is wy");
		// 釋出事件
		context.publishEvent(event);
	}
}

列印資訊
其他的資訊!org.springframework.context.event.ContextRefreshedEvent[source=org[email protected]1dff3a2: startup date [Sun Feb 28 14:43:48 CST 2016]; root of context hierarchy]
資訊內容是:my name is wy


列印的資訊中我們看到,打印出來我們監聽到的事件的同時,也監聽到了內建的事件的訊息。

spring的內建事件:

1. ContextRefreshedEvent:ApplicationContext容器初始化或者重新整理的時候會觸發這個事件。

2. ContextStartedEvent:當使用ConfigurableApplicationContext(applicationContext的子介面)介面的start方法啟動ApplicationContext容器的時候觸發這個事件。

3. ContextClosedEvent:當使用ConfigurableApplicationContext(applicationContext的子介面)介面的close方法啟動ApplicationContext容器的時候觸發這個事件。

4. ContextStoppedEvent:當使用ConfigurableApplicationContext(applicationContext的子介面)介面的stop方法啟動ApplicationContext容器的時候觸發這個事件。

5. RequestHandledEvent:web相關的事件,只能用在DispatcherServlet的web應用中,在使用spring作為mvc控制器的時候,處理完使用者的請求後,系統會自動的呼叫。

另外webSocket服務中,還有,SessionConnectedEvent、SessionConnectEvent、SessionDisconnectEvent三個事件。