ApplicationContext和BeanFactory一样都是bean的容器,而BeanFactory是一切Bean容器的父类,ApplicationContext继承于BeanFactory(继承之BeanFactory的子类)
ApplicationContext包含了BeanFactory的所有功能,并且扩展了其他功能。先从ApplicationContext的案例入手,代码如下:
ApplicationContext ctx = new ClassPathXmlApplicationContext("application.xml");
ctx.getBean("myBean");

可以看出ApplicationContext和BeanFactory的用法基本一样,初始化之后就可以直接获取Bean了,那么我们就先从ApplicationContext的初始化入手,也就是先从ClassPathXmlApplicationContext的构造函数入手,代码如下:

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
 public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException { //调用父类的构造函数
super(parent);
//设置配置xml
setConfigLocations(configLocations);
//ApplicationContext初始化
if (refresh) {
refresh();
}
}
初始化配置xml可以传入数组形式,设置方法setConfigLocations代码如下:
 public void setConfigLocations(@Nullable String... locations) {
if (locations != null) {
Assert.noNullElements(locations, "Config locations must not be null");
this.configLocations = new String[locations.length];
for (int i = 0; i < locations.length; i++) {
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}
else {
this.configLocations = null;
}
}

主要用于解析配置的xml信息,将xml路径信息赋值给configLocations,设置了配置信息之后就需要对ApplicationContext进行初始化操作了,也就是最后一步的refresh方法了,代码如下:

 @Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
//准备刷新
prepareRefresh(); // Tell the subclass to refresh the internal bean factory.
//初始化BeanFactory,并进行XML文件读取
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context.
//对BeanFactory进行各种功能扩展
prepareBeanFactory(beanFactory); try {
// Allows post-processing of the bean factory in context subclasses.
//子类覆盖方法做额外对处理
postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context.
//激活各种BeanFactory处理器
invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation.
//注册拦截Bean创建对Bean处理器,这里只是注册,真正调用是在getBean对时候
registerBeanPostProcessors(beanFactory); // Initialize message source for this context.
//为上下文初始化Message
initMessageSource(); // Initialize event multicaster for this context.
//初始化应用消息广播器
initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses.
//留给子类来初始化其他对Bean
onRefresh(); // Check for listener beans and register them.
//在所有注册对bean中寻找Lestener bean,注册到消息广播器中
registerListeners(); // Instantiate all remaining (non-lazy-init) singletons.
//初始化剩下对单例bean
finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event.
//完成刷新过程,通知生命周期处理器刷新过程,同时发出ContextRefreshEvent通知别人
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
} // Destroy already created singletons to avoid dangling resources.
destroyBeans(); // Reset 'active' flag.
cancelRefresh(ex); // Propagate exception to caller.
throw ex;
} finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
}

主要过程为:

1.初始化前对准备工作,对系统属性或者环境变量的验证
2.初始化BeanFactory,并进行xml文件读取,相当于复用了BeanFactory的配置文件读取解析过程,相当于进行了一次BeanFactory的初始化,剩下的都是对BeanFactory的扩展了
3.对BeanFactory进行功能填充(如@Autowired @Qualifier注解对支持等)
4. 子类覆盖父类方法做额外的处理(postProcessBeanFactory方法是空函数,方便子类进行扩展)
5.激活各种BeanFactory处理器
6.注册拦截bean创建的bean处理器
7.剩下的可以看代码中的注解
 
接下来再细看,初始化前的准备验证直接跳过,直接看如何初始化BeanFactory的,
 protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}

第一步初始化BeanFactory,进行xml配置读取解析

第二步返回BeanFactory

 @Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
大致过程如下:
1.创建DefaultListableBeanFactory对象,BeanFactory的初始化实际也是创建了这个对象
2.指定序列号ID
3.定制BeanFactory
4.加载BeanDefinition
5.使用全局变量记录BeanFactory实例
 
这里的第三步的customizeBeanFactory方法是对BeanFactory的扩展,添加了@Qualifier和@Autowired的支持
loadBeanDefinitions方法是加载BeanDefinition,首先是加载Xml,使用XmlBeanDefinitionReader的loadBeanDefinitions方法进行配置文件的加载注册和BeanFactory的逻辑一样
 
在BeanFactory初始化之后就是对BeanFactory的扩展,也就是prepareBeanFactory方法及之后的内容
 
 protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); // Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); // BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this); // Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); // Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
} // Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}

方法主要内容是:

1.增加对SPEL语言的支持(如#{XXX.xxx}设置属性)

2.增加对属性编辑器的支持

3.设置依赖功能可忽略的接口

4.注册一些固定依赖的属性

5.增加AspectJ的支持

6.将相关环境变量及属性注册以单例模式注册

 
接下来再看下初始化非延迟加载单例的bean
 protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
} // Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
} // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
} // Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null); // Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration(); // Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}

这里的26行的freezeConfiguration方法是对bean定义的冻结,也就是说bean注册之后就不可改了,而ApplicationContext默认说会将所有的单例bean提前进行初始化的,也就是方法preInstantiateSingletons方法

 @Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
} // Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
} // Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
高频面试题:ApplicationContext和BeanFactory的区别?
1.BeanFactory是容器所有容器接口的父类,提供了最基本的bean相关的功能,而ApplicationContext是继承之BeanFactory,在BeanFactory的基础上扩展了更多的功能
2.ApplicationContext的初始化过程就包含了BeanFactory的初始化过程,如何额外扩展,
3.BeanFactory中的bean是在获取的时候才初始化,而ApplicationContext是初始化的时候就初始化所有的单例bean(好处是在启动的时候就可以检查到不合法的bean)
4.ApplicationContext增加了SPEL语言的支持(#{xx.xx}等配置)、 消息发送、响应机制(ApplicationEventPublisher)、支持了@Qualiiar和@Autowired等注解
 

spring源码解析-ApplicationContext解析的更多相关文章

  1. Spring源码入门——DefaultBeanNameGenerator解析 转发 https://www.cnblogs.com/jason0529/p/5272265.html

    Spring源码入门——DefaultBeanNameGenerator解析   我们知道在spring中每个bean都要有一个id或者name标示每个唯一的bean,在xml中定义一个bean可以指 ...

  2. 从零开始学spring源码之xml解析(一):入门

    谈到spring,首先想到的肯定是ioc,DI依赖注入,aop,但是其实很多人只是知道这些是spring核心概念,甚至不知道这些代表了什么意思,,作为一个java程序员,怎么能说自己对号称改变了jav ...

  3. 从零开始学spring源码之xml解析(二):默认标签和自定义标签解析

    默认标签: 上一篇说到spring的默认标签和自定义标签,发现这里面东西还蛮多的.决定还是拆开来写.今天就来好好聊聊这两块是怎么玩的,首先我们先看看默认标签: private void parseDe ...

  4. Spring源码阅读-ApplicationContext体系结构分析

    目录 继承层次图概览 ConfigurableApplicationContext分析 AbstractApplicationContext GenericApplicationContext Gen ...

  5. Spring源码之ApplicationContext

    ​ 本文是针对Srping的ClassPathXMLApplicationContext来进行源码解析,在本篇博客中将不会讲述spring Xml解析注册代码,因为ApplicationContext ...

  6. Spring源码入门——XmlBeanDefinitionReader解析

    接上篇[] ,我们看到BeanDefinitionReader解决的是从资源文件(xml,propert)到BeanDefinition集合的过程.所以BeanDefinitionReader接口有两 ...

  7. Spring源码入门——AnnotationBeanNameGenerator解析

    ---恢复内容开始--- 接上篇,上篇解析了DefaultBeanGenerator生成bean name的过程(http://www.cnblogs.com/jason0529/p/5272265. ...

  8. Spring源码入门——DefaultBeanNameGenerator解析

    我们知道在spring中每个bean都要有一个id或者name标示每个唯一的bean,在xml中定义一个bean可以指定其id和name值,但那些没有指定的,或者注解的spring的beanname怎 ...

  9. spring源码:ApplicationContext的增强功能(li)

    ApplicationContext作为资源加载器:ApplicationContext作为事件发布者: Java原生提供了事件发布机制------EventObject对象作为发布的事件,Event ...

  10. 【Spring 源码】ApplicationContext源码

    ApplicationConetxt体系

随机推荐

  1. vue项目中使用bpmn-基础篇

    内容概述 本系列“vue项目中使用bpmn-xxxx”分为五篇,均为自己使用过程中用到的实例,手工原创,目前属于陆续更新中.主要包括vue项目中bpmn使用实例.应用技巧.基本知识点总结和需要注意事项 ...

  2. Spring5参考指南:容器扩展

    文章目录 BeanPostProcessor自定义bean BeanFactoryPostProcessor自定义配置元数据 使用FactoryBean自定义实例化逻辑 Spring提供了一系列的接口 ...

  3. 【JAVA基础】10 Object类

    1. Object类概述 是类层次结构的根类 每个类都使用 Object 作为超类 所有类都直接或者间接的继承自该类 所有对象(包括数组)都实现这个类的方法. 2. Object的构造方法 publi ...

  4. iOS9.2.1 App从AppStore上下载闪退问题

    首先这是小编的第一篇文章,我是一名做iOS开发的小白,出于爱好会更新发表些相关的技术文章,偶尔也会发些视频.恳请大家不要去嘲笑一个努力的人,要是做的不好请多多评论,反正我也不改. 好了!敲黑板!!说正 ...

  5. Ant 环境安装

    1.下载安装 Ant,配置环境变量 进入 http://ant.apache.org/bindownload.cgi 下载 Ant 配置环境变量 新建 ANT_HOME 配置 Path 环境变量 配置 ...

  6. Linux文件删除空间未释放

    当系统空间使用量过大需要清理空间或者清理某个文件时,有时会出现执行了删除命令之后磁盘空间并没有释放,很多人首次遇到该情况时会比较困惑,在考虑是不是像windows系统的回收站一样,删除只是逻辑删除到回 ...

  7. 算法---BitMap

    问题: 假设有3亿个整数(范围0-2亿),如何判断某一个树是否存在.局限条件一台机器,内存500m. 常规的思路:我们可以将数据存到一个集合中,然后判断某个数是否存在:或者用一个等长的数组来表示,每个 ...

  8. MAC使用Scrapy遇到的坑

    MAC版本:EI Captain Python版本: 2.7.10 MAC默认没有安装pip,所以首先 sudo easy_install pip 然后安装Scrapy: sudo pip insta ...

  9. C# 基础知识系列- 16 开发工具篇

    0. 前言 这是C# 基础知识系列的最后一个内容讲解篇,下一篇是基础知识-实战篇.这一篇主要讲解一下C#程序的结构和主要编程工具. 1. 工具 工欲善其事必先利其器,在实际动手之前我们先来看看想要编写 ...

  10. CentOS-6.5操作系统安装

    1.创建Linux虚拟机(如图所示) 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 1.10 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.18 ...