引言

Spring通过一个配置文件描述Bean及Bean之间的依赖关系,利用Java语音的反射功能实例化Bean并建立Bean之间的依赖关系。Spring的IoC容器在完成这些底层工作的基础上,还提供了Bean实例缓存、生命周期、Bean实例代理、事件发布、资源装载等服务。

Bean工厂(org.springframework.beans.factory.Beanfactory)是Spring框架最核心的接口,它提供了高级IoC的配置机制。BeanFacotry使管理不同类型的Java对象成为可能,应用上下文(org.springframework.context.ApplicationContext)建立在BeanFactory基础之上,提供了更多面向应用的功能,它提供了国际化支持和框架事件体系,更易于创建实际应用。一般我们将BeanFactory成为IoC容器,而称ApplicationContext为应用上下文,但是有时为了行文方便,也将ApplicationContext成为Spring容器。

对于二者的用途,我们可以进行简单的划分:BeanFactory是Spring框架的基础设施,面向Spring本身;ApplicationContext面向使用Spring框架的开发者,几乎所有的应用场合都可以直接使用ApplicationContext而非底层的BeanFactory。

BeanFactory介绍

BeanFactory是一个通用的类工厂,可以创建并管理各种类的对象。这些可被创建和管理的对象仅仅是一个POJO,Spring称之为Bean。

BeanFactory的类体系结构

Spring为BeanFactory提供了多种实现,最常见的是XmlBeanFactory,但是在Spring3.2中已被废弃,建议使用XmlBeanDefinitionReader、DefaultListableBeanFactory替代。BeanFactory的类继承体系设计优雅,堪称经典。

BeanFactory接口位于类结构树的顶端,它最主要的方法就是getBean(String beanName),该方法从容器中返回特定名称的Bean。BeanFactory的功能通过其他接口得到不断扩展:

  • ListableBeanFactory:该接口定义了访问容器中Bean基本信息的若干方法,如查看Bean的个数、获取某一类型Bean的配置名、查看容器是都保罗某一个Bean等;
  • HierarchicalBeanFactory:父子级联IoC容器的接口,子容器可以通过接口方法访问父容器;
  • ConfigurableBeanFactory:这是一个重要的接口,增强了IoC容器的可定制性。它定义了设置类装载器、属性编译器、容器初始化后置处理器等方法;
  • AutowireCapableBeanFactory:定义了将容器中的Bean按某种规则(如按名字匹配、按类型匹配等)进行自动装配的方法;
  • SingletonBeanFactory:定义了允许在运行期向容器注册单实例Bean的方法;
  • BeanDefinitionRegistry:Spring配置文件中每一个节点元素在Spring容器里都通过一个BeanDfinition对象表示,它描述了Bean的配置信息。而BeanDefinitionRegistry接口提供了向容器手工注册BeanDefinition对象的方法。

ApplicationContext介绍

如果说BeanaFactory是Spring的"心脏",那么ApplicationContext就是完整的"身躯"了。ApplicationContext由BeanFactory派生而来,提供了更多面向实际应用的功能。在BeanFactory中,很多功能需要以编程的方式实现,而在ApplicationContext中则可以通过配置方式实现。

ApplicationContext类体系结构

ApplicationContext的主要实现类是ClassPathXmlApplicationContext和FileSystemXmlApplicationContext,前者默认从类路径加载配置文件,后者默认从文件系统中装载配置文件。ApplicationContext继承了HierachicalBeanFactory和ListableBeanFactory接口,在此基础上,还通过其他接口扩展了BeanFactory的功能:

  • ApplicationEvenPublisher:让容器拥有发布应用上下文事件的功能,包括容器启动事件、关闭事件等。实现了ApplicationListener事件监听接口的Bean可以接收到容器事件,并对事件进行响应处理。在ApplicationContext抽象实现类AbstractApplicationContext中存在一个ApplicationEvent,它负责保存所有的监听器,以便在容器产生上下文事件时通知这些事件监听者;
  • MessageSource:为应用提供i18n国际化消息访问的功能;
  • ResourcePatternResolver:所有ApplicationContext实现类都实现了类似于PathMatchingResourcePatternResolver的功能,可以通过带前缀的Ant风格的资源文件路径装载Spring的配置文件;

    LifeCycle:该接口提供了start()和stop()两个方法,主要用于控制异步处理过程。在具体使用时,该接口同时被ApplicationContext实现及具体Bean实现,ApplicationContext会将start/stop的信息传递给容器中所有实现了该接口的Bean,以达到管理控制JMX、任务调度等目的。

ConfigurableApplicationContext扩展于ApplicationContext,新增了两个主要的方法:refresh()和close()方法,让ApplicationContext具有启动、刷新和关闭应用上下文的能力。在应用上下文关闭的情况下调用refresh()即可启动应用上下文,在已经启动的状态下掉哦那个refresh()则可清楚缓存并重新装载配置信息,而调用close()则可关闭应用上下文。这些接口方法为容器的控制管理带来了便利,但作为开发者,我们并不需要过多关心这些方法。

常见的ApplicationContext实现类

ClassPathXmlApplicationContext

如果配置文件放置在类路径下,则可以优先考虑使用ClassPathXmlApplicationContext实现类。

FileSystemXmlApplicationContext

如果配置文件放置在文件系统的路径下,则可以优先考虑使用FileSystemApplicationContext实现类。

AnnontationConfigApplicationContext

基于注解类的配置

BeanFactory和ApplicationContext的不同处

BeanFactory在初始化容器时,并未实例化Bean,直到第一次访问某个Bean才实例化目标Bean;而ApplicationContext则在初始化应用上下文就实例化所有单实例的Bean。因此,ApplicationContext的初始化时间会比BeanFactory稍长一些,不过稍后的调用则没有"第一次惩罚"的问题。

WebApplicationContext类体系结构

WebApplicationContext是专门为Web应用准备,它允许从相对于Web根目录的路径中装载配置文件完成初始化工作。从WebApplicationContext中可以获得ServletContext的引用,整个Web应用上下文对象将作为属性放置到ServletContext中,以便web应用环境可以访问Spring应用上下文。Spring专门为此提供了一个工具类WebApplicationContextUtils,通过该类的getWebApplicationContext(ServletContext sc)方法,可以从ServletContext中获取WebApplicationContext实例。

在非Web应用的环境中,Bean只用singleton和prototype两中作用域。WebApplicationContext为Bean添加了三个新的作用域:request、session和global session。

由于Web应用比一般的应用拥有更多的特性,因此WebApplicationContext扩展了ApplicationContext。WebApplicationContext定义了一个常量ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,在上下文启动时,WebApplicationContext实例即以此为键放置在ServletContext的属性列表中,可以通过以下从Web容器中获取WebApplicationContext:

WebApplicationContext  wac = (WebApplicationContext)servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);

这就是WebApplicationContextUtils工具类getWebApplicationContext(ServletContext sc)方法的内部实现方式。这样Spring的Web应用上下文和Web容器的上下文应用就可以实现互访,二者实现了融合。

ConfigurableWebApplicationContext扩展了WebApplicationContext,它允许通过配置的方式实例化WebApplicationContext,同时定义了两个重要的方法:

  • setServletContext(ServletContext servletContext):为Spring设置Web应用上下文,以便二者整合;
  • setConfigLocations(String[] configLocatons):设置Spring配置文件地址,一般情况下,配置文件地址时相对Web根目录的地址,如/WEN-INF/**.xml等,但是用户也可以使用带资源类型前缀的地址。

WebApplicationContext初始化

WebApplicationContext的初始化方式和BeanFactory、ApplicationContext有所区别,因为WebApplicationContext需要ServletContext实例,也就说,它必须在拥有Web容器的前提下才能完成启动工作。可以在web.xml中配置自启动的Servlet或定义Web容器监听器(ServletContextListener),借助二者中的任何一个,就可以完成启动Spring Web应用上下文的工作。

Spring分别提供了用于启动WebApplicationContext的Servlet和Web容器监听器:

  • org.springframework.web.context.ContextLoaderServlet;
  • org.springframework.web.context.ContextLoadeerListener。

    二者的内部实现了启动WebApplicationContext实例的逻辑,只要根据Web容器的具体情况下选择二者之一,并在web.xml中完成配置即可。
<!--指定配置文件-->
<context-param>
<param-name>
contextConfigLocation
</param-name>
<param-value>
/WEB-INF/**-dao.xml,/WEB-INF/**-service.xml
</param-value>
</context-param> <!--声明Web容器监听器--->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

ContextLoaderListener通过Web容器上下文参数contextConfigLocation获取Spring配置文件的位置。用户可以指定多个配置文件,用逗号】空格或冒号分隔均可。

对于未带资源类型前置的配置文件,WebApplicationContext默认这些路径相对于Web的部署根路径。当然,也可以采用带资源类型前缀的路径配置。

如果在不支持容器监听器的低版本Web容器中,则可以采用ContextLoaderServlet完成相同的工作。

<context-param>
<param-name>
contextConfigLocation
</param-name>
<param-value>
/WEB-INF/**-dao.xml,/WEB-INF/**-service.xml
</param-value>
</context-param> <!---声明自启动的Servlet-->
<servlet>
<servlet-name>
springContextLoaderServlet
</servlet-name>
<servlet-class>
org.springframework.web.context.ContextLoaderServlet
</servlet-class> <!--启动顺序-->
<load-on-startup>1</load-on-startup>
</servlet>

用于WebApplicationConext需要使用日志功能,所以用户将Log4J的配置文件在类路径WEB-INF/classes下,这时Log4J引擎即可顺利启动,如果Log4J配置文件放置在其他位置,那么用户必须在wen.xml中指定Log4J配置文件的位置,Spring为启动Log4J引擎提供了两个类似与启动WebApplicationContext的实现类:Log4jConfigServlet和Log4jConfigListener,不管采用哪种方式,都必须保证能够在装载Spring配置文件前先装载log4J配置信息

<context-param>
<param-name>
contextConfigLocation
</param-name>
<param-value>
/WEB-INF/**-dao.xml,/WEB-INF/**-service.xml
</param-value>
</context-param> <!--指定Log4J配置文件-->
<context-param>
<param-name>
log4jConfigLocation
</param-name>
<param-value>
/WEB-INF/log4j.properties
</param-value>
</context-param> <!--装载Log4J配置文件的自启动Servlet-->
<servlet>
<servlet-name>
log4jConfigServlet
</servlet-name>
<servlet-class>
org.springframework.web.utils.Log4jConfigServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet> <servlet>
<servlet-name>
springContextLoaderServlet
</servlet-name>
<servlet-class>
org.springframework.web.context.ContextLoaderServlet
</servlet-class> <load-on-startup>2</load-on-startup>
</servlet>

注意上面将log4jConfigServlet的启动顺序号设置为1,而将springContextLoadeServlet的启动顺序号设置为2。这样,前者将启动,完成装载Log4J配置文件并初始化Log4J引擎的工作,紧接着后者再启动。如果使用Web监听器,则必须将Log4jConfigListener放置在ContextLoaderListener的前面。采用以上配置方式,Spring将自动使用XmlWebApplicationContext启动Spring容器,即通过XML文件为Spring容器提供Bean的配置信息。

如果使用标注@Configuration的Java类提供配置信息,则web.xml需要按以下方式配置:

<web-app>
<!--通过指定context参数,让Spring使用AnnontationConfigWebApplicationContext而非XmlWebApplicationContext启动容器-->
<context-param>
<param-name>
contextClass
</param-nae>
<param-value>
org.springframework.web.context.AnnotationConfigApplicationContext
</param-value>
</context-param> <!--指定标注@Configuration的配置类,多个可以使用逗号或空格分隔-->
<context-param>
<param-name>
contextConfigLocation
</param-name>
<param-value>
org.aming.myproject.config.AppConfig
</param-value>
</context-param> <!--ContextLoaderListener监听器根据上面的配置使用AnnotationConfigWebApplicationContext根据contextConfigLoaction指定的配置类启动Spring容器-->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListner
</listener-class>
</listener>
</web-app>

ContextLoaderListener如果发现配置了contextClass上下文参数,就会使用参数所指定的WebApplicationContext实现类(AnnotationConfigWebApplicationContext)初始化容器,该实现类会根据contextConfigLocation上下文参数指定的@Configuration的配置类所提供的Spring配置信息初始化容器。

BeanFactory和ApplicationContext的简单介绍的更多相关文章

  1. String关于BeanFactory与ApplicationContext的简单区别

    1.创建的方式不同 ApplicationContext: ApplicationContext context = new ClassPathXmlApplicationContext(" ...

  2. Spring容器、BeanFactory和ApplicationContext,及3种装配Bean的方式

    目录 一. spring容器理解 二. BeanFactory和ApplicationContext之间的关系 三. BeanFactory详情介绍 四.ApplicationContext介绍 五. ...

  3. Spring(二)核心容器 - 简介 、BeanFactory、ApplicationContext

    目录 前言 1.容器简介 2.容器的结构 2.1 BeanFactory 2.2 ApplicationContext 2.2.1 ConfigurableApplicationContext 2.2 ...

  4. 理解Spring 容器、BeanFactory 以及 ApplicationContext

    一.spring 容器理解 spring 容器可以理解为生产对象(Object)的地方,在这里容器不只是帮助我们创建对象那么简单,它负责了对象的整个生命周期-创建.装配.销毁.而这里对象的创建管理的控 ...

  5. BeanFactory和ApplicationContext的区别

     1.BeanFactory和ApplicationContext的异同点: 相同点:     两者都是通过xml配置文件加载bean,ApplicationContext和BeanFacotry相比 ...

  6. spring中的BeanFactory与ApplicationContext的作用和区别?

    BeanFactory类关系继承图 1. BeanFactory类结构体系: BeanFactory接口及其子类定义了Spring IoC容器体系结构,由于BeanFactory体系非常的庞大和复杂, ...

  7. Spring基于 Annotation 的简单介绍

    tyle="margin:20px 0px 0px; font-size:14px; line-height:26px; font-family:Arial"> 1.使用 @ ...

  8. Spring中BeanFactory与ApplicationContext的区别

    BeanFactory:Bean工厂接口,是访问Spring Bean容器的根接口,基本Bean视图客户端.从其名称上即可看出其功能,即实现Spring Bean容器的读取. ApplicationC ...

  9. 从头认识Spring-1.14 SpEl表达式(1)-简单介绍与嵌入值

    这一章节我们来讨论一下SpEl表达式的简单介绍与嵌入值. 1.SpEl表达式简单介绍 Spring Excpression Language (SpEL)语言支持在执行时操作和查询对象 事实上就是在执 ...

随机推荐

  1. Linux下lz4解压缩命令小结

    lz4是一个让"人见人爱.花见花开"的压缩算法,能够在多核上很好的扩展.lz4在压缩率上略微逊色, 但是在解压速度上有着惊人的优势 (大概是gzip的3倍(多次测试对比)).因为压 ...

  2. RabbitMQ Exchange详解以及Spring中Topic实战

    前言 AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计.消息中间件主要用于组件之间的解耦. 业务需求 ...

  3. python的Web框架,类视图

    类视图 范式 from django.views import View # 继承View class IndexView(View): def get(self, request): #写法和函数视 ...

  4. 复制神器Ditto使用方法详细说明

    1.普通的粘贴快捷键设置: 我设置成ctrl+1 --> ctrl+10.但是注意,有些程序里ctrl有特殊功能,这样ctrl+[0-9]键会出现问题,所以建议将粘贴快捷键设置的复杂一点,例如c ...

  5. 后端自测必备神器-PostMan

    作为后端的一个小小菜鸟,写代码没有把握,总怕出错,也不敢直接扔测试,这个时候就需要一个神器能够辅助自己去测试各种情况,让自己安心的交给测试,嗯……这时神器出场了------PostMan.在一个偶然的 ...

  6. Docker 启动遇到 Error starting daemon: Error initializing network controller 错误

    docker 版本 1.10.3 一台装有 docker 的机器重启后,没法启动,/var/log/messages 展示如下错误信息: May 17 11:11:14 gziba-hc03 syst ...

  7. jQuery之$.ajax()方法详解及实例

    1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type: 要求为String类型的参数,请求方式(post或get)默认为get.注意其他http请求方法,例如 ...

  8. 2017-07-29 中文代码示例教程之Java编程一天入门

    Java编程一天入门 v0.0.1 alpha 共享协议 本作使用署名-非商业使用-禁止演绎协议共享. 前言 Java入门代码用中文写(举例如下)更能被新手理解. 由于至今没有看到类似教程, 在此抛砖 ...

  9. 【读书笔记】iOS-分类与协议

    分类与协议是Object-C特有概念,分类(Category)可以认为是一种继承性的扩展,而协议(Protocol)可以理解为Java中的Interface(接口)或者C++的纯虚类. 参考资料:&l ...

  10. CSS 实现隐藏滚动条同时又可以滚动

    方法1: 利用 css 3 的新特性  -webkit-scrollbar, 但是这种方式只兼容chrome,不兼容 火狐 和 IE. /* for Chrome */ .content::-webk ...