ApplicationContext再理解
在SpringApplication的初始化过程一文中,我们介绍了对ApplicationContext初始化的过程,随着介绍的深入,我们不禁对于应用上下文又产生了新的问题,它到底是什么,为什么要在一开始初始化出来。
这里就简单介绍一下。
Spring既然要负责应用程序中那么多对象的创建管理,就像苹果要生产那么多的手机(对象)一样,肯定有一个专门搞对象的地方。苹果生产手机的地方叫工厂,比如富士康,但放在软件开发中,对于Spring搞对象的地方我们就不叫工厂了,而叫做容器。是的,容器的概念在java中你最熟悉的莫过于Tomcat了,它正是一个运行Servlet的web容器,而Spring要想实现依赖注入功能,就离不开对象生产的容器——如果没有容器负责对象的创建管理,你的程序代码只是喊要对象了,Spring也无处给你啊。实际上,容器是Spring框架实现功能的核心,容器不只是帮我们创建了对象那么简单,它负责了对象整个的生命周期的管理——创建、装配、销毁。关于Spring的这个容器你最常听闻的一个术语就是IOC容器。所谓IOC,是一种叫控制反转的编程思想,网上有很通俗易懂的总结,我就不胡乱阐述了。总之一句话,我的应用程序里不用再过问对象的创建和管理对象之间的依赖关系了,都让IOC容器给代劳吧,也就是说,我把对象创建、管理的控制权都交给Spring容器,这是一种控制权的反转,所以Spring容器才能称为IOC容器。不过这里要厘清一点:并不是说只有Spring的容器才叫IOC容器,基于IOC容器的框架还有很多,并不是Spring特有的。
好了,终于把Spring的容器概念阐述的差不多了,但有什么卵用呢?光有容器你其实什么都干不了!你以为容器那么科幻,跟叮当猫面前的百宝袋一样,你想要啥它就给你啥?实际上,容器里面什么都没有,决定容器里面放什么对象的是我们自己,决定对象之间的依赖关系的,也是我们自己,容器只是给我们提供一个管理对象的空间而已。那么,我们怎么向容器中放入我们需要容器代为管理的对象呢?这就涉及到Spring的应用上下文了。什么是应用上下文呢,你可以简单的理解成就是将你需要Spring帮你管理的对象放入容器的那么一种。。一种。。额。。一种容器对象——是的,应用上下文即是Spring容器的一种抽象化表述;而我们常见的ApplicationContext本质上说就是一个维护Bean定义以及对象之间协作关系的高级接口。额,听起来是不是很抽象拗口?那你再读一遍呢。。。
这里,我们必须明确,Spring的核心是容器,而容器并不唯一,框架本身就提供了很多个容器的实现,大概分为两种类型:一种是不常用的BeanFactory,这是最简单的容器,只能提供基本的DI功能;还有一种就是继承了BeanFactory后派生而来的应用上下文,其抽象接口也就是我们上面提到的的ApplicationContext,它能提供更多企业级的服务,例如解析配置文本信息等等,这也是应用上下文实例对象最常见的应用场景。有了上下文对象,我们就能向容器注册需要Spring管理的对象了。对于上下文抽象接口,Spring也为我们提供了多种类型的容器实现,供我们在不同的应用场景选择——
- AnnotationConfigApplicationContext:从一个或多个基于java的配置类中加载上下文定义,适用于java注解的方式;
- ClassPathXmlApplicationContext:从类路径下的一个或多个xml配置文件中加载上下文定义,适用于xml配置的方式;
- FileSystemXmlApplicationContext:从文件系统下的一个或多个xml配置文件中加载上下文定义,也就是说系统盘符中加载xml配置文件;
- AnnotationConfigWebApplicationContext:专门为web应用准备的,适用于注解方式;
- XmlWebApplicationContext:从web应用下的一个或多个xml配置文件加载上下文定义,适用于xml配置方式。
关于上面这一点,我在文章Spring——BeanFactory(1)中也有提到过。
有了以上理解,问题就很好办了。你只要将你需要IOC容器替你管理的对象基于xml也罢,java注解也好,总之你要将需要管理的对象(Spring中我们都称之问bean)、bean之间的协作关系配置好,然后利用应用上下文对象加载进我们的Spring容器,容器就能为你的程序提供你想要的对象管理服务了。
ApplicationListener再理解
ApplicationContext事件机制是观察者设计模式的实现,通过ApplicationEvent类和ApplicationListener接口,可以实现ApplicationContext事件处理。
这是ApplicationListener源码:
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E var1);
}
这里通过一个简单的自定义事件来说明:
可以自定义事件,然后做完业务处理后手动发出。同上集成某个监听接口,接收到事件后进行业务处理
事件定义:
public class EmailEvent extends ApplicationEvent{
private String address;
private String text;
public EmailEvent(Object source, String address, String text){
super(source);
this.address = address;
this.text = text;
}
public EmailEvent(Object source) {
super(source);
}
//......address和text的setter、getter
}
监听定义
public class EmailNotifier implements ApplicationListener{
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof EmailEvent) {
EmailEvent emailEvent = (EmailEvent)event;
System.out.println("邮件地址:" + emailEvent.getAddress());
System.our.println("邮件内容:" + emailEvent.getText());
} else {
System.our.println("容器本身事件:" + event);
}
}
}
业务触发
public class SpringTest {
public static void main(String args[]){
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
//创建一个ApplicationEvent对象
EmailEvent event = new EmailEvent("hello","[email protected]","This is a test");
//主动触发该事件
context.publishEvent(event);
}
再介绍几个内置的事件: