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);
- }
- }
- <?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;
- }
- }
- 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.springframework.context.support.ClassPathXmlApplicationContext@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三个事件。