Spring源码学习--Spring中的BeanFactory和ApplicationContext

文章来源

https://www.zhihu.com/question/38597460?sort=created
https://blog.csdn.net/u011202334/article/details/51509235
https://blog.csdn.net/hi_kevin/article/details/7325554




一 第一种说法

Spring中的BeanFactory和ApplicationContext和BeanFactory相比,提供了更多的扩展功能,但是这还不是主要的区别,主要区别在于BeanFactory是延迟加载,举个例子:如果Bean没有完全注入,BeanFactory加载后,会在你第一次调用getBean方法时才会抛出异常;而ApplicationContext会在初始化的时候就加载并且检查,这样的好处是可以及时检查依赖是否完全注入;所以通常来说我们会选择使用ApplicationContext.

BeanFactory和ApplicationContext都支持BeanPostProcessor\BeanFactoryPostProcessor的使用,但是两者之间的区别在于:BeanFactory需要手动注册,而ApplicationContext则是自动注册的.

BeanFactory是Spring中相当古老的Factory了,比如说XmlBeanFactory就是一种相当电影的BeanFactory.所以原始的BeanFactory就无法支持诸如AOP\WEB应用等许多插件

ApplicationContext接口是有BeanFactory接口派生出来的,所以提供了BeanFactory的所有功能.ApplicationContext是一种更加面向框架的工作方式以及对上下文进行分层和实现继承.并且ApplicationContext还额外提供了一下功能.

  • MessageSource:提供国际化的消息访问
  • 资源访问:如URL和文件
  • 事件传播
  • 载入多个(有继承关系)上下文,使得每一个上下文都专注于一个特定的层次,比如应用的web层



BeanFacotry是spring中比较原始的Factory。如XMLBeanFactory就是一种典型的BeanFactory。原始的BeanFactory无法支持spring的许多插件,如AOP功能、Web应用等。

ApplicationContext接口,它由BeanFactory接口派生而来,因而提供BeanFactory所有的功能。ApplicationContext以一种更向面向框架的方式工作以及对上下文进行分层和实现继承,ApplicationContext包还提供了以下的功能:
• MessageSource, 提供国际化的消息访问
• 资源访问,如URL和文件
• 事件传播
• 载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层

1.利用MessageSource进行国际化

BeanFactory是不支持国际化功能的,因为BeanFactory没有扩展Spring中MessageResource接口。相反,由于ApplicationContext扩展了MessageResource接口,因而具有消息处理的能力(i18N).

2.强大的事件机制(Event)

基本上牵涉到事件(Event)方面的设计,就离不开观察者模式。不明白观察者模式的朋友,最好上网了解下。因为,这种模式在java开发中是比较常用的,又是比较重要的。 ApplicationContext的事件机制主要通过ApplicationEvent和ApplicationListener这两个接口来提供的,和java swing中的事件机制一样。即当ApplicationContext中发布一个事件的时,所有扩展了ApplicationListener的Bean都将会接受到这个事件,并进行相应的处理。

Spring提供了部分内置事件,主要有以下几种:

  • ContextRefreshedEvent :ApplicationContext发送该事件时,表示该容器中所有的Bean都已经被装载完成,此ApplicationContext已就绪可用
  • ContextStartedEvent:生命周期 beans的启动信号
  • ContextStoppedEvent: 生命周期 beans的停止信号
  • ContextClosedEvent:ApplicationContext关闭事件,则context不能刷新和重启,从而所有的singleton bean全部销毁(因为singleton bean是存在容器缓存中的)

虽然,spring提供了许多内置事件,但用户也可根据自己需要来扩展spring中的事物。注意,要扩展的事件都要实现ApplicationEvent接口。

3.底层资源的访问

ApplicationContext扩展了ResourceLoader(资源加载器)接口,从而可以用来加载多个Resource,而BeanFactory是没有扩展ResourceLoader.

4.对Web应用的支持

与BeanFactory通常以编程的方式被创建不同的是,ApplicationContext能以声明的方式创建,如使用ContextLoader。当然你也可以使用ApplicationContext的实现之一来以编程的方式创建ApplicationContext实例 。

ContextLoader有两个实现:ContextLoaderListener和ContextLoaderServlet。它们两个有着同样的功能,除了listener不能在Servlet 2.2兼容的容器中使用。自从Servelt 2.4规范,listener被要求在web应用启动后初始化。很多2.3兼容的容器已经实现了这个特性。使用哪一个取决于你自己,但是如果所有的条件都一样,你大概会更喜欢ContextLoaderListener;关于兼容方面的更多信息可以参照ContextLoaderServlet的JavaDoc。

这个listener需要检查contextConfigLocation参数。如果不存在的话,它将默认使用/WEB-INF/applicationContext.xml。如果它存在,它就会用预先定义的分隔符(逗号,分号和空格)分开分割字符串,并将这些值作为应用上下文将要搜索的位置。ContextLoaderServlet可以用来替换ContextLoaderListener。这个servlet像listener那样使用contextConfigLocation参数。

5.其它区别

1).BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化,这样,我们就不能发现一些存在的Spring的配置问题。而ApplicationContext则相反,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误。

2).BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册




BeanFactory类关系继承图
这里写图片描述

1. BeanFactory类结构体系

BeanFactory接口及其子类定义了Spring IOC容器体系结构,由于BeanFactory体系非常的庞大和复杂,因此要理解Spring IoC,需要先理清BeanFactory的继承机构。

这里写图片描述

2. ApplicationContext的结构体系

ApplicationContext接口是一个BeanFactory基础上封装了更多功能的,Spring中最为常用的IOC容器,其包含两个子接口:ConfigurableApplicationContext、WebApplicationContext。

ConfigurableApplicationContext其结构体系如下:
这里写图片描述

详细的结构体系如下:

a.AbstractApplicationContext结构体系如下:

这里写图片描述

b.ConfigurablePortletApplicationContext体系结构如下:

这里写图片描述

c.ConfigurableWebApplicationContext结构体系如下:

这里写图片描述

WebApplicationContext体系结构如下:

这里写图片描述




1、容器是spring的核心,使IoC管理所有和组件

2、spring的两种容器:

a、BeanFactoy
b、ApplicationContext应用上下文

3、BeanFactory:BeanhFactory使用延迟加载所有的Bean,为了从BeanhFactory得到一个Bean,只要调用getBean()方法,就能获得Bean

4、ApplicationContext:

a、提供文本信息解析,支持I18N
b、提供载入文件资源的通用方法
c、向注册为监听器的Bean发送事件
d、ApplicationContext接口扩展BeanFactory接口
e、ApplicationContext提供附加功能

5、ApplicationContext的三个实现类:

a、ClassPathXmlApplication:把上下文文件当成类路径资源
b、FileSystemXmlApplication:从文件系统中的XML文件载入上下文定义信息
c、XmlWebApplicationContext:从Web系统中的XML文件载入上下文定义信息

6、在默认情况下,Bean全都是单态,在<bean>中的singleton为false

7、<bean>中的id属性必须遵循Java规范,而name属性可以不遵循

8、Bean的实例化的时候需要一些初始化的动作,同样当不再使用的时候,需要从容器中将其销毁

9、对象的初始化:<bean init-method="方法名">

10、对象的销毁:<bean destroy-method="方法名">

销毁对象的过程:
a、主线程先被中断
b、Java虚拟机使用垃圾回收机制回收Bean对象



Spring的IoC容器就是一个实现了BeanFactory接口的可实例化类。事实上,Spring提供了两种不同的容器:一种是最基本的BeanFactory,另一种是扩展的ApplicationContext。BeanFactory 仅提供了最基本的依赖注入支持,而 ApplicationContext 则扩展了BeanFactory ,提供了更多的额外功能。二者对Bean的初始化也有很大区别。BeanFactory当需要调用时读取配置信息,生成某个类的实例。如果读入的Bean配置正确,则其他的配置中有错误也不会影响程序的运行。而ApplicationContext 在初始化时就把 xml 的配置信息读入内存,对 XML 文件进行检验,如果配置文件没有错误,就创建所有的Bean ,直接为应用程序服务。相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。

ApplicationContext会利用Java反射机制自动识别出配置文件中定义的BeanPostProcessor、InstantiationAwareBeanPostProcessor和BeanFactoryPostProcessor,并自动将它们注册到应用上下文中;而BeanFactory需要在代码中通过手工调用addBeanPostProcessor()方法进行注册。

Bean装配实际上就是让容器知道程序中都有哪些Bean,可以通过以下两种方式实现:

配置文件(最为常用,体现了依赖注入DI的思想)
编程方式(写的过程中向BeanFactory去注册)
  1. BeanFactory负责读取bean配置文档,管理bean的加载,实例化,维护bean之间的依赖关系,负责bean的声明周期。

  2. ApplicationContext除了提供上述BeanFactory所能提供的功能之外,还提供了更完整的框架功能:

    a. 国际化支持
    b. 资源访问:Resource rs = ctx. getResource(“classpath:config.properties”), “file:c:/config.properties”
    c. 事件传递:通过实现ApplicationContextAware接口

  3. 常用的获取ApplicationContext的方法:

    FileSystemXmlApplicationContext:从文件系统或者url指定的xml配置文件创建,参数为配置文件名或文件名数组
    ClassPathXmlApplicationContext:从classpath的xml配置文件创建,可以从jar包中读取配置文件
    WebApplicationContextUtils:从web应用的根目录读取配置文件,需要先在web.xml中配置,可以配置监听器或者servlet来实现

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

这两种方式都默认配置文件为web-inf/applicationContext.xml,也可使用context-param指定配置文件

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/myApplicationContext.xml</param-value>
</context-param>

猜你喜欢

转载自blog.csdn.net/u013412772/article/details/80338074