容器功能的扩展
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. IOS杂记

    - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { //Using code from http://stackoverfl ...

  2. IOS自定义仪表盘

      登录|注册     周海锋 的专栏 Objective-C/Cocos2d/Cocos2d-x/Php/JS       目录视图 摘要视图 订阅 2016软考项目经理实战班    学院周年礼-顶 ...

  3. log4j中文乱码解决方案

    项目中log4j在英文版linux下输出中文日志为乱码. 由于log4j配置文件中没有设置编码格式(encoding),所以log4j就使用系统默认编码.导致乱码. 解决方法是设置编码格式UTF-8, ...

  4. 改变CSS样式

    改变CSS样式 1.改变HTML元素样式的语法 //改变HTML样式的语法 document.getElementById(id).style.property = new style 例子: < ...

  5. Action访问Servlet API

    访问Servlet API 1.通过ActionContent类访问Servlet API ActionContext中访问Servlet API的几个常用的方法: (1)Map getApplica ...

  6. mysql正则匹配解决查询一个字段是否在另一个字段中

    select b.filter_name , count(*) from at_goods a , at_search_filter bwhere a.application REGEXP b.fil ...

  7. Java程序员必备的6款最佳开发工具

    工欲善其事,必先利其器.每一个Java程序员都有其惯用的工具组件.对于Java程序员,各种有用的软件和工具泛滥成灾.初级开发人员要么找不到合适的工具,要么在寻找过程中浪费了大量的时间.下面,我将为大家 ...

  8. JQuery多媒体插件jQuery Media Plugin使用详解

    malsup jquery media plugin 该插件可以播放多种类型的多媒体文件包括:Flash, Quicktime, Windows Media Player, Real Player, ...

  9. oracle数据库导入导出dmp文件oracle命令

    在控制台下导入imp scott/密码@orcl file=文件路径 full=Y 导出 整个数据库TEST 用户名system  密码1234 exp system/1234@TEST file=文 ...

  10. 移除virbr0

    在我们使用虚拟机管理器的图形界面来安装虚拟机的时候,自动创建虚拟网桥和虚拟网卡.另外,我们很少会在一个虚拟机中再安装一个虚拟机,所以,我们可以将宿主机上的网桥删除.方法如下: # virsh net- ...