Spring 容器
在 Spring 应用中,应用对象生存于 Spring 容器中,Spring 容器负责创建对象、装配对象、配置对象以及管理它们的整个生命周期。
如何理解容器 (container)
首先可以通过这篇了解下 DI 和 IoC ,链接。
容器是 Spring 的核心。Spring 容器使用 DI 管理构成应用的组件,它会创建相互协作的组件之间的关联。
两种 Spring 容器实现
- bean 工厂:由
org.springframework.beans.factory.BeanFactory
接口定义,是最简单的容器,提供基本的 DI 支持。但是对于大多数应用来说太低级了,所以推荐使用下面一种。 - 应用上下文:由
org.springframework.context.ApplicationContext
接口定义,基于 BeanFactory 构建,并提供应用框架级别的服务。以下讨论的都是这种容器实现。
常见的应用上下文
1. ClassPathXmlApplicationContext
从类路径下的一个或多个 XML 配置文件中加载上下文定义,把应用上下文的定义文件作为类资源。
代码实现如下:
ApplicationContext context = new ClassPathXmlApplicationContext("knight.xml");
2. FileSystemXmlApplicationContext
从文件系统下的一个或多个 XML 配置文件中加载上下文定义。
代码实现如下:
ApplicationContext context = new FileSystemXmlApplicationContext("/User/ethan/knight.xml");
区别:ClassPathXmlApplicationContext 默认会去 classPath 路径下找。classPath 路径指的就是编译后的 classes 目录。FileSystemXmlApplicationContext 默认是去项目的路径下加载,可以是相对路径,也可以是绝对路径。
3.其他几种应用上下文
AnnotationConfigApplicationContext
AnnotationConfigWebApplicationContext
XmlWebApplicationContext
应用上下文准备就绪之后,就可以调用应用上下文的getBean()
方法从 Spring 容器中获取 bean。
bean 的生命周期
传统的 java 应用中,生命周期就是 new 完就是创建了,一旦该 bean 不再被使用,由 Java 自动进行垃圾回收。
Spring 容器中的 bean 生命周期会复杂很多,具体如下:
Spring 对 bean 进行实例化
Spring 将值和 bean 的引用注入到 bean 对应的属性中
-
如果实现了下面接口,分别会做不同操作:
3.1 如果 bean 实现了
BeanNameAware
接口,Spring 将bean 的 ID 传递给setBeanName()
方法。关于BeanNameAware 以及下面的 BeanFactoryAware 可以查看这篇。Aware 这个词在这里可以翻译为知觉
3.2 如果 bean 实现了
BeanFactoryAware
接口,Spring 将调用setApplicationCOntext()
方法,将BeanFactory
容器实例传入。方法本身的目的是让Spring立即处理工厂中所有Bean的定义,并且将这些Bean全部实例化。因为Spring默认实例化Bean的情况下,采用的是lazy机制,换言之,如果不通过getBean()方法(BeanFactory或者ApplicationContext的方法)获取Bean的话,那么为了节省内存将不实例话Bean,只有在Bean被调用的时候才实例化他们。
3.3 如果 bean 实现了
ApplicationContextAware
接口,Spring 将调用setApplicationContext()
方法,将 bean 所在的应用上下文实例传进来。在某些特殊的情况下,Bean需要实现某个功能,但该功能必须借助于Spring容器才能实现,此时就必须让该Bean先获取Spring容器,然后借助于Spring容器实现该功能。为了让Bean获取它所在的Spring容器,可以让该Bean实现ApplicationContextAware接口。
3.4 如果 bean 实现了
BeanPostProcessor
接口,Spring 将调用setPostProcessBeforeInitialization()
方法。如果我们想在Spring容器中完成bean实例化、配置以及其他初始化方法前后要添加一些自己逻辑处理。我们需要定义一个或多个BeanPostProcessor接口实现类,然后注册到Spring IoC容器中。
3.5 如果 bean 实现了
InitializingBean
接口,Spring 将调用afterPropertiesSet()
方法。类似地,如果 bean 使用 init-method 声明了初始化方法,该方法也会被调用。InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候都会执行该方法。
3.6 如果 bean 实现了
BeanPostProcessor
接口,Spring 将调用setPostProcessAfterInitialization()
方法。类似3.4, 一前一后。 此时,bean 已经准备就绪,可以被应用程序使用了,它们将一直驻留在上下文中,知道该应用上下文被销毁。
如果 bean 实现了
DisposableBean
接口,Spring 将调用它的destory()
接口方法。同样,如果 bean 使用 destory-method 声明了 销毁方法,该方法也会被调用。