Spring 提供了以下两种不同类型的容器。
它是最简 单的容器,给 DI 提供了基本的支持,用org.springframework.beans.factory.BeanFactory 接口来定义。BeanFactory 或者相关的接口,如 BeanFactoryAware,InitializingBean,DisposableBean,在 Spring 中仍然存在具有大量的与 Spring 整合的第三方框架的反向兼容性的目的。
在 Spring 中,有大量对 BeanFactory 接口的实现。其中,最常被使用的是 XmlBeanFactory 类。这个容器从一个 XML 文件中读取配置元数据,由这些元数据来生成一个被配置化的系统或者应用。
继承了BeanFactory接口,拥有BeanFactory的全部功能,并且扩展了很多高级特性,每次容器启动时就会创建所有的对象。它可以加载配置文件中定义的 bean,将所有的 bean 集中在一起,当有请求的时候分配 bean。
ApplicationContext 接口实现:
FileSystemXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你需要提供给构造器 XML 文件的完整路径。
ClassPathXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你不需要提供 XML 文件的完整路径,只需正确配置 CLASSPATH 环境变量即可,因为,容器会从 CLASSPATH 中搜索 bean 配置文件。
被称作 bean 的对象是构成应用程序的支柱也是由 Spring IoC 容器管理的。bean 是一个被实例化,组装,并通过 Spring IoC 容器所管理的对象。这些 bean 是由用容器提供的配置元数据创建的。Spring IoC 容器完全由实际编写的配置元数据的格式解耦。基于 XML 的配置文件、基于注解的配置、基于 Java 的配置、把配置元数据提供给 Spring 容器。
在 Spring 中定义一个 bean 时,你必须声明该 bean 的作用域,Spring 框架支持以下五个作用域,分别为 singleton、prototype、request、session 和 globalsession。
| 作用域 | 描述 |
| Singleton | 在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,默认值 |
| Prototype | 每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean() |
| Request | 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境 |
| Session | 同一个HTTP Session共享一个Bean,不同Session使用不同的Bean,仅适用于WebApplicationContext环境 |
| global-session | 一般用于Portlet应用环境,该作用域仅适用于WebApplicationContext环境 |
当一个 bean 被实例化时,它可能需要执行一些初始化使它转换成可用状态。同样,当 bean 不再需要,并且从容器中移除时,可能需要做一些清除工作。
1. Bean的实例化
Spring对Bean进行实例化(相当于 new XXX()),对于 BeanFactory一般是延迟实例化,就是说调用 getBean方法才会实例化,但是对于 ApplicationContext,当容器初始化完成之后,就完成了所有Bean的实例化工作。实例化的对象被包装在 BeanWrapper对象中, BeanWrapper提供了设置对象属性的接口,从而避免了使用反射机制设置属性。
2. InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor这个接口主要是帮助你在Bean实例化之前做一些操作。它继承自 BeanPostProcessor接口,其中postProcessBeforeInstantiation()方法是在目标对象实例化之前调用的方法,可以返回目标实例的一个代理用来代替目标实例。postProcessPropertyValues方法是在属性值被设置到目标实例之前调用,可以修改属性的设值。
3. 设置属性(依赖注入)
实例化后的对象被封装到 BeanWrapper对象中,并且此时对象是一个原生状态,并没有执行依赖注入。紧接着,Spring根据 BeanDefinition中的信息进行依赖注入。并且通过 BeanWrapper提供的设置属性的接口完成依赖注入。
4. 注入Aware接口
Spring 会检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给Bean。各种各样的Aware接口,其作用就是在对象实例化完成后将Aware接口定义中规定的依赖注入到当前实例中。比较常见的 ApplicationContextAware接口,实现了这个接口的类都可以获取到一个 ApplicationContext对象,当容器中每个对象的实例化过程走到 BeanPostProcessor前置处理这一步时,容器会检测到之前注册到容器的 ApplicationContextAwareProcessor,然后就会调用其 postProcessorBeforeInitialization()方法,检查并5. BeanPostProcessor的postProcessBeforeInitialzation方法
经过上述步骤后,Bean对象已经被正确构造了,如果你想要对象被使用之前在进行自定义的处理,可以通过 BeanPostProcessor接口实现。该接口提供了两个方法 其中 postProcessBeforeInitialzation(Objectbean,StringbeanName) 方法;当前正在初始化的bean对象会被传递进来,我们就可以对这个Bean做任何处理,这个方法会先于 InitializingBean执行,因此称为前置处理。
6. InitializingBean与init-method
如果Bean实现了 InitializingBean接口,Spring将调用它们的 afterPropertiesSet方法,作用与在配置文件中对Bean使用 init-method声明初始化的作用一样,都是在Bean的全部属性设置成功后执行的初始化方法。afterPropertiesSet 方法与前置处理不同的是,由于其没有把Bean对象传进来,因此在这一步没有办法处理对象本身,只能增加一些额外的逻辑。
7.BeanPostProcess的postProcessAfterInitialzation方法
BeanPostProcess的 postProcessAfterInitialzation(Objectbean,StringbeanName) 方法;当前正在初始化的bean对象会被传递进来,我们就可以对这个bean做任何处理。这个函数会在 InitializingBean完成后执行,因此称为后置处理。
8. Bean初始化结束
经过以上的工作以后,Bean的初始化就结束了,Bean将一直驻留在应用上下文中给应用使用,知道应用上下文被销毁。
9. DispostbleBean接口
如果Bean实现了 DispostbleBean接口,Spring将调用它的 destroy方法,作用与在配置文件中对Bean使用 destroy-method属性的作用是一样的,都是在Bean实例销毁前执行的方法。