容器功能的扩展
ApplicationContext用于扩展BeanFactory中现有的功能。究竟多出了哪些功能,进一步探索。写法上:
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beanFactoryTest.xml"));

ApplicationContext bf = new ClassPahtApplicationContext("beanFactoryTest.xml");
还是以ClassPahtApplicationContext作为切入点:
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}

ClassPahtApplicationContext可以对数据进行解析并进行加载,而对于解析及功能实现都是在refresh()中实现

setConfigLocations(String... locations):设置配置路径
用于解析给定的路径数组,如果数组中包含特殊符号如$(var),那么resolvePath中会搜索匹配的变量并替换

refresh();扩展功能
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();

// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);

try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);

// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);

// Initialize message source for this context.
initMessageSource();

// Initialize event multicaster for this context.
initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.
onRefresh();

// Check for listener beans and register them.
registerListeners();

// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event.
finishRefresh();
}
}
}
1_ prepareRefresh()初始化的准备工作,例如对系统属性或者环境变量进行准备及验证。
2_ obtainFreshBeanFactory 初始化BeanFactory,并进行XML文件读取
ClassPathXmlApplicationContext包含着BeanFactory所提供的一切特征,在这一步中将会复用BeanFactory中的配置文件读取解析及其它功能,这一步之后,ClassPathXmlApplicationContext实际上就包含了BeanFactory所提供的功能,也就是可以进行Bean的提取等基础操作了
3_ prepareBeanFactory() 对BeanFactory进行各种功能填充
@Qualifier与@Autowired正式在这一步骤中提供的支持
4_ postProcessBeanFactory() 子类覆盖方法做额外处理
postProcessBeanFactory是一个空函数,需要自己重写子类,覆盖方法来方便在业务上进行扩展
5_ invokeBeanFactoryPostProcessors(beanFactory) 激活各种BeanFactory处理器
6_ registerBeanPostProcessors(beanFactory) 注册拦截bean创建的bean处理器,这里只是注册,真正的调用在getBean的时候。
7_ initMessageSource() 为上下文初始化Message源,即对不同语言的消息体进行国际化处理。
8_ initApplicationEventMulticaster() 初始化应用消息广播器,并犯法如“applicationEventMuliticaster”bean中。
9_ onRefresh()留个子类初始化其他的bean
10_ registerListeners() 在所有注册的bean中查找listener bean,注册到消息广播器中
11_ finishBeanFactoryInitialization(beanFactory) 初始化剩下的单实例(非惰性的)。
12_ finishRefresh()完成刷新功能,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人。

1__ prepareRefrsh 主要做些准备工作,例如对系统属性和环境变量的初始化及验证
里边两个主要的方法initPropertySources(),validateRequiredProperties()。
initPropertySources,用户根据自己的需要重写initPropertySources()方法,并在方法进行个性化的属性处理及设置
validateRequiredProperties,对属性验证。如:工程需要某个设置(VAR)从系统环境变量中获取,如果用户没配这个变量,那么系统不能工作。这一要求在spring就可以自定义一个类集成ClassPathXmlApplicationContext,在initPropertySources()里用getEnviroment().setRequiredProperties("VAR")设置这个属性,那么在验证的就是验证这个属性,没有就会报错。当然也要在使用的时候替换掉原有的ClassPathXmlApplicationContext:ApplicationContext bf = new MyApplicationPathApplicationContext("test.xml");
2__ obtainFreshBeanFactory
加载BeanFactory,经过这个函数后,ApplicationContext就有了BeanFactory的全部功能。这个方法里的步骤:
1.创建DefaultListableBeanFactory
前面用的BeanFactory bf = new XmlBeanFactory("text.xml")中的XmlBeanFactory继承自DefaultListenBeanFactory,并提供了XmlBeanDefinitionReader属性,也就是说DefaultListenBeanFactory是容器的基础。必须首先实例化。
2.是定序列化ID
3.定制BeanFactory
customizeBeanFactory(beanFactory)
4.加载BeanDefinition
5.使用全局变量记录BeanFactory类实例。因为DefaultListenBeanFactory类型的变量beanFacotory是函数内的局部变量,所有要用全局变量来记录解析结果。
3_ customizeBeanFactory(beanFactory)
这里已经开始了对BeanFactory的扩展,在基本容器的基础上,增加了是否允许覆盖是否允许扩展的设置并提供了@Qualifier和@Autowired的支持。允许覆盖允许扩展只是判断了是否为空,为空就进行设置,但是在此之前哪个地方来设置它并没有看见,还是在子类的customizeBeanFactory覆盖方法中进行设置。接下来就是加载BeanDefinition,需要XmlBeanDefinitionReader来读取xml,这里首先初始化它,调用loadBeanDefinitions方法,和前面说的Beanfactory的加载一模一样。
这里还有很多细节。(书的135页)
3__ prepareBeanFactory() 功能扩展
1增加SPEL语言的支持
2增加属性注册编辑器
spring在DI的时候类似于Date这种属性无法识别,会报错,可以有两种方法解决
1:使用自定义属性编辑器
2:注册spring自带的属性编辑器CustomDateEditor
3添加ApplicationContextAwareProcessor处理器
对于beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this))的主要目的就是注册个BeanPostProcessor。真正的逻辑还在ApplicationContextAwareProcessor中。ApplicationContextAwareProcessor实现BeanPostProcessor接口。之前在bean实例化的时候,也就是spring激活bean的init-method的前后,会调用BeanPostProcessor的postProcessBeforeInitialization方法和postProcessAfterInitialization方法,同样对于ApplicationContextAwareProcessor我们也看这两个方法。
postProcessAfterInitialization方法没有做过多逻辑处理
postProcessBeforeInitialization方法,其中主要的逻辑是调用了invokeAwareInterfaces,从这个方法代码中能看出主要是实现这些Aware接口在被初始化的后,可以获得一些对应的资源。
4.设置忽略依赖。将ApplicationContextAwareProcessor注册后,invokeAwareInterfaces方法中间接调用的Aware已经不是普通的bean了,需要在spring做bean的依赖注入的时候忽略他们。
5.注册依赖。当注册了依赖解析后,例如当注册了对BeanFactory.Class的解析依赖后,当bean的属性注入的时候,一旦检测属性为BeanFactory类型便会将实例beanFactory注入进去。
4_ postProcessBeanFactory BeanFactory的后处理
11_ finishBeanFactoryInitialization(beanFactory)
完成BeanFactory的初始化工作,其中包括ConversionService的设置、配置冻结以及非延迟加载的bean的初始化工作。
1.ConversionService的设置。之前说过用自定义类型转化器可以从String转Date,spring中还提供了另外一种转换方式:使用Converter。
2.冻结配置。冻结所有的bean定义说明注册的bean定义将不能被修改或进行任何进一步处理。
3.初始化非延迟加载。ApplicationContext实现的默认方式就是在启动的时候将所有的单例bean提前实例化,通常只是好事,因为这样在配置的中的错误能马上就发现。这个实例化的过程是在finishBeanFactoryInitialization中完成的。
12_ finishRefresh
在spring中还提供了Lifecycle接口,包好start/stop方法,实现此接口后Spring会保证在启动的时候调用其start方法开始生命周期,并在关闭的时候调用stop方法接受生命周期,通常用来配置后台程序,在启动后一直运行(如对MQ进行轮询)。
1.initLifecycleProcessor:当ApplicationContext启动或停止时,会通过LifecycleProcessor来与所有的bean的周期做状态更新,而在使用前需要初始化
2.onRefresh:启动所有实现了Lifecycle接口的bean
3.publishEvent:当完成ApplicationContext初始化的时候,要通过Spring中的时间发布机制来发出ContextRefreshEvent事件,保证对应的监听器可以进一步的逻辑处理。

spring源码深度解析-2功能扩展的更多相关文章

  1. spring源码深度解析— IOC 之 容器的基本实现

    概述 上一篇我们搭建完Spring源码阅读环境,spring源码深度解析—Spring的整体架构和环境搭建 这篇我们开始真正的阅读Spring的源码,分析spring的源码之前我们先来简单回顾下spr ...

  2. Spring源码深度解析之Spring MVC

    Spring源码深度解析之Spring MVC Spring框架提供了构建Web应用程序的全功能MVC模块.通过策略接口,Spring框架是高度可配置的,而且支持多种视图技术,例如JavaServer ...

  3. Spring源码深度解析之事务

    Spring源码深度解析之事务 目录 一.JDBC方式下的事务使用示例 (1)创建数据表结构 (2)创建对应数据表的PO (3)创建表和实体之间的映射 (4)创建数据操作接口 (5)创建数据操作接口实 ...

  4. spring源码深度解析— IOC 之 默认标签解析(上)

    概述 接前两篇文章  spring源码深度解析—Spring的整体架构和环境搭建  和  spring源码深度解析— IOC 之 容器的基本实现 本文主要研究Spring标签的解析,Spring的标签 ...

  5. spring源码深度解析— IOC 之 默认标签解析(下)

    在spring源码深度解析— IOC 之 默认标签解析(上)中我们已经完成了从xml配置文件到BeanDefinition的转换,转换后的实例是GenericBeanDefinition的实例.本文主 ...

  6. spring源码深度解析— IOC 之 开启 bean 的加载

    概述 前面我们已经分析了spring对于xml配置文件的解析,将分析的信息组装成 BeanDefinition,并将其保存注册到相应的 BeanDefinitionRegistry 中.至此,Spri ...

  7. Spring源码深度解析之数据库连接JDBC

    Spring源码深度解析之数据库连接JDBC JDBC(Java Data Base Connectivity,Java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供 ...

  8. Spring源码深度解析系列-----------org.springframework.aop-3.0.6.RELEASE

    Spring源码深度解析系列-----------org.springframework.aop-3.0.6.RELEASE

  9. spring源码深度解析—Spring的整体架构和环境搭建

    概述 Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用.Spring是于2003 年兴起的一个轻量级的Java 开发框 ...

随机推荐

  1. Poj(1274),二分图匹配

    题目链接:http://poj.org/problem?id=1274 The Perfect Stall Time Limit: 1000MS   Memory Limit: 10000K Tota ...

  2. 附加数据库对于服务器失败(Microsoft.SqlServer.Smo),无法升级数据库,因为它是只读的,或者具有只读文件

    今天在将一个 SQL Server 2000 数据库附加到 SQL Server 2005时出现如下的错误:附加数据库对于服务器失败(Microsoft.SqlServer.Smo),无法升级数据库t ...

  3. C#中的异步和同步

    同步 同步(英语:Synchronization [ˌsɪŋkrənaɪ'zeɪʃn]),指对在一个系统中所发生的事件(event)之间进行协调,在时间上出现一致性与统一化的现象.说白了就是多个任务一 ...

  4. 3094 寻找sb4

    3094 寻找sb4  时间限制: 1 s  空间限制: 32000 KB  题目等级 : 黄金 Gold 题解  查看运行结果     题目描述 Description sb有一天和sml吵架了,她 ...

  5. 启动Print Spooler服务提示:"错误1068,依存服务或无法启动"

    本人windows8操作系统,从网上看到在运行中输入  sc config spooler depend= rpcss 即可,试了下果然有效.具体原因待了解.

  6. Android 计算器界面

    高仿魅族魅蓝NOTE 2风格 <?xml version="1.0" encoding="utf-8"?> <TableLayout xmln ...

  7. C# 多线程 Invoke BeginInvoke

    Invoke在线程中等待Dispatcher调用指定方法,完成后继续下面的操作. BeginInvoke不必等待Dispatcher调用制定方法,直接继续下面的操作. 来自:百度知道 这个在线程中操作 ...

  8. Windows Live Writer代码高亮插件对比

    一.Paste ASVisual Studio Code 参考:http://www.cnblogs.com/mikelij/archive/2010/11/13/1876199.html 插件下载: ...

  9. jquery之clone()方法详解

    clone()函数用于克隆当前匹配元素集合的一个副本,并以jQuery对象的形式返回.你也可以简单地理解为:克隆当前jQuery对象. 你还可以指定是否复制这些匹配元素(甚至它们的子元素)的附加数据( ...

  10. CentOS最小化安装后,增加GNOME桌面

    背景:下载CentOS 7的安装包后,在虚拟机上安装. 上来就遇到一个问题:提示需要开启intel vt-x. 这个进入BIOS,在CPU的设置中开启即可. 然后怀着兴奋的心情,开始各种下一步的安装, ...