编写启动类

    public static void main(String[] args) throws Exception {ApplicationContext context = new ClassPathXmlApplicationContext("zhou.xml");A aFactoryBean = (A) context.getBean("aFactoryBean");System.out.println(aFactoryBean);}

执行ClassPathXmlApplicationContext构造方法

 public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)throws BeansException {//这里调用父类的构造方法,进行一些对象的操作以及属性的赋值super(parent);//主要是设置应用程序上下文的配置路径,创建对象环境ConfigurableEnvironment、处理ClassPathXmlApplicationContext传入的占位符setConfigLocations(configLocations);if (refresh) {//spring的核心完成bean对象的实例化以及初始化操作refresh();}}

在AbstractApplicationContext 类中

@Overridepublic 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();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();}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();}}}

prepareRefresh() 做容器刷新前的准备工作,主要有

  • 设置容器的启动时间
this.startupDate = System.currentTimeMillis();
  • 容器关闭的标志位 false
this.closed.set(false);
  • 容器激活的标志位 true
this.active.set(true);
  • initPropertySources() 留给子类去扩展的,实现为空
  • 创建并获取环境对象,验证属性文件是否都已经放入到环境中
getEnvironment().validateRequiredProperties();
  • 判断预刷新的应用监听器是否为空,如果为空则将监听器添加到这个集合中,否则清空集合,在进行添加

if (this.earlyApplicationListeners == null) {this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);}else {this.applicationListeners.clear();this.applicationListeners.addAll(this.earlyApplicationListeners);}
  • 创建刷新前的事件监听器集合这个是Set集合
this.earlyApplicationEvents = new LinkedHashSet<>();

obtainFreshBeanFactory()

  1. 创建spring容器对象,DefaultListableBeanFactory
  2. 加载xml配置文件的属性值到BeanFactory,最重要的是创建BeanDefinition

里面具体执行

 protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {// 初始化BeanFactory,并进行XML文件读取,并将得到的BeanFactory记录在当前实体的属性中refreshBeanFactory();// 返回当前实体的beanFactory属性return getBeanFactory();}

refreshBeanFactory()

  1. 首先判断是否存在BeanFacotry,如果存在则销毁、关闭
if (hasBeanFactory()) {destroyBeans();closeBeanFactory();}
  1. 创建BeanFactory,并设置序列化id
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
  1. 定制BeanFactory,设置相关的属性,包含是否覆盖同名称不同定义的对象,以及是否允许循环依赖
customizeBeanFactory(beanFactory);
 protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {//是否允许覆盖同名称的不同定义的对象// 如果属性allowBeanDefinitionOverriding不为空,设置给beanFactory对象相应属性if (this.allowBeanDefinitionOverriding != null) {beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}//是否允许bean之间存在循环依赖// 如果属性allowCircularReferences不为空,设置给beanFactory对象相应属性if (this.allowCircularReferences != null) {beanFactory.setAllowCircularReferences(this.allowCircularReferences);}}
  1. 初始化documentReader,并进行xml配置文件的读取和解析
loadBeanDefinitions(beanFactory);

getBeanFactory()
返回当前实体的beanFactory属性

prepareBeanFactory(beanFactory);

准备beanFactory,完成bean工厂的初始化操作,实际就是往里面放属性值

内部具体的逻辑

1.设置bean的classLoader为当前context的classLoader

beanFactory.setBeanClassLoader(getClassLoader());
  1. 设置beanFactory的语言表达式处理器 SpelExpressionParser
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
  1. 设置beanFactory的默认的propertyEditor,主要是对bean的属性设置管理的一个工具类
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
  1. 添加BeanPostrocessor ApplicationContextAwareProcessor这个类用来完成某些Aware对象的注入
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
  1. 设置忽略自动装配的接口,因为这些接口是由容器通过set方法注入的。因此使用Autowire注入的时候要将这些接口忽略
     beanFactory.ignoreDependencyInterface(EnvironmentAware.class);beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);beanFactory.ignoreDependencyInterface(MessageSourceAware.class);beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
  1. 设置几个自动装配的特殊规则,当进行IOC初始化的时候,如果有多个实现,就用指定的对象进行注入
     beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);beanFactory.registerResolvableDependency(ResourceLoader.class, this);beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);beanFactory.registerResolvableDependency(ApplicationContext.class, this);
  1. 添加BeanPostProcessor, ApplicationListerDetector,将用于检测内部bean的一个早期后置处理器作为监听器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
  1. 增加对aspectJ的支持
     // 增加对AspectJ的支持,在java中织入分为三种方式,分为编译器织入,类加载器织入,运行期织入,编译器织入是指在java编译器,采用特殊的编译器,将切面织入到java类中,// 而类加载期织入则指通过特殊的类加载器,在类字节码加载到JVM时,织入切面,运行期织入则是采用cglib和jdk进行切面的织入// aspectj提供了两种织入方式,第一种是通过特殊编译器,在编译器,将aspectj语言编写的切面类织入到java类中,第二种是类加载期织入,就是下面的load time weavingif (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()));}
  1. 注册默认的系统环境bean到一级缓存中
     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());}

postProcessBeanFactory(beanFactory);

用于子类覆盖方法做额外的处理,用于扩展

invokeBeanFactoryPostProcessors(beanFactory);

调用 BFPP处理器

  1. 获取当前应用上下文的beanFactoryPostProcessors变量的值,并实例化调用执行已经注册的beanFactoryPorstProcessor
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
  1. 与此同时,如果发现LoadTimeWeaver,并准备织入
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}

registerBeanPostProcessors(beanFactory);

注册bean处理器,这里只是注册,真正的调用在getBean()

initMessageSource();

初始化message资源,这个是进行国际化处理,

initApplicationEventMulticaster();

初始化多事件广播器

onRefresh();

留给子类初始化其他的bean

registerListeners();

注册监听器,在所有注册的bean中查找listener,注册到消息广播器中

finishBeanFactoryInitialization(beanFactory);

初始化剩下的单例bean(重点

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory)
  1. 为上下文初始化类型转换器(conversionService)
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));}
  1. 如果beanFactory之前没有注册嵌入值解析器,则注册默认的嵌入值解析器,用于注解属性值的解析
    XML文件时,有一个嵌入值解析器PropertySourcePlaceHolderConfigure
if (!beanFactory.hasEmbeddedValueResolver()) {beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));}
  1. 初始化LoadTimeWeaverAwareBean,以便尽早的注册其转换器
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);for (String weaverAwareName : weaverAwareNames) {getBean(weaverAwareName);}

4.将临时的类加载器置为null,主要是禁止临时类加载器进行类型匹配

beanFactory.setTempClassLoader(null);

5.冻结配置,注册的bean定义信息将不能被修改

beanFactory.freezeConfiguration();

6.进行实例化剩下的单例对象

beanFactory.preInstantiateSingletons();

finishRefresh();

完成刷新,发布相应的时间,完成beanactory的初始化创建工作

resetCommonCaches();

重置通用缓存

 protected void resetCommonCaches() {ReflectionUtils.clearCache();AnnotationUtils.clearCache();ResolvableType.clearCache();CachedIntrospectionResults.clearClassLoader(getClassLoader());}

Spring源码-执行流程相关推荐

  1. Spring源码——MVC流程

    前言 最近回顾了一下Spring源码,准备用思维导图的方式简单的将整个源码内容的流程展示出来,思维导图.图片等文件更新在https://github.com/MrSorrow/spring-frame ...

  2. Spring源码——ClassPathXmlApplicationContext流程

    前言 最近回顾了一下Spring源码,准备用思维导图的方式简单的将整个源码内容的流程展示出来,思维导图.图片等文件更新在https://github.com/MrSorrow/spring-frame ...

  3. Spring源码——XmlBeanFactory流程

    前言 最近回顾了一下Spring源码,准备用思维导图的方式简单的将整个源码内容的流程展示出来,思维导图.图片等文件更新在https://github.com/MrSorrow/spring-frame ...

  4. 跟随一笔交易来看以太坊c++客户端源码执行流程 / 源码分析

    本文初步分析了一个交易在以太坊内部的处理流程,涉及到交易的接收,检查,执行,同步,区块的构建以及挖矿,结合前面一篇基于黄皮书的理解总结,对以太坊有了更多的认识.因为主要的工作在c++层面,所以这里以c ...

  5. Glide源码--执行流程

    Glide的基本使用 看一下郭神的博客,Android图片加载框架最全解析(八),带你全面了解Glide 4的用法 图片加载机制的基本流程 我们从这行代码看起 Glide.with(this).loa ...

  6. python多线程gil_Python 多线程、多进程 (一)之 源码执行流程、GIL

    一.python程序的运行原理 许多时候,在执行一个python文件的时候,会发现在同一目录下会出现一个__pyc__文件夹(python3)或者.pyc后缀(python2)的文件 Python在执 ...

  7. python多线程执行同样代码_Python 多线程、多进程 (一)之 源码执行流程、GIL

    一.python程序的运行原理 许多时候,在执行一个python文件的时候,会发现在同一目录下会出现一个__pyc__文件夹(python3)或者.pyc后缀(python2)的文件 Python在执 ...

  8. 想读Spring源码?先从这篇「 极简教程」开始

    来自:Java中文社群 为什么要阅读源码?这是一个有趣的问题,类似的问题还有,为什么要看书?为什么要爬山? 这也是一个哲学问题,我想每个人都有不同的答案,下面我是对阅读源码好处的一些思考.(PS:也欢 ...

  9. 想读Spring源码?先从这篇「 极简教程」开始吧...

    为什么要阅读源码?这是一个有趣的问题,类似的问题还有,为什么要看书?为什么要爬山? 这也是一个哲学问题,我想每个人都有不同的答案,下面我是对阅读源码好处的一些思考. (PS:也欢迎你在评论区留言补充) ...

最新文章

  1. idea中文乱码问题
  2. linux查看java进程cpu占用过高
  3. [C++]有关深复制与copy constructor的一些问题与实例
  4. python自动化测试框架结构_基于Python的HTTP接口自动化测试框架实现
  5. mysql log all sql_记录一次mysqlbinlog恢复过程
  6. java Flink使用addSink方法保存流到mysql数据库中
  7. BZOJ 1025: [SCOI2009]游戏
  8. mysql内存表主从复制_MySQL的内存表在主从同步的注意事项_MySQL
  9. web开源FlowPlayer视频播放器
  10. 燕无锡计算机学校,第二十七届中国儿童青少年计算机表演赛无锡赛区决赛成绩-无锡少年宫.doc...
  11. html drag 例子,html5 drag事件用法
  12. 新唐NUC980读取U盘配置
  13. java模拟器怎么调中文_电脑java模拟器(javagame模拟器)
  14. ipcm 核间通信相关 ---(1)
  15. Windows系统 修改 dns
  16. c语言关于continue的题,10道c语言基础题1、C语言的跳转语句中,对于break和continue说法正确的是_______. A、contin...
  17. USB VID和PID
  18. STM32+Zigbee的使用
  19. 缩略图方式下, 资源管理器,不能显示文件名
  20. 2019智慧树python答案大全_2020智慧树Python语言应用答案

热门文章

  1. 实现厕所门锁智能化,案使用涂鸦 Zigbee 模组作为主控,功耗低,效率高(内涵原理图)
  2. 当听到一个啰里吧嗦、不着边际的极品需求之时
  3. 弘辽科技:拼多多多多场景推广的收藏准确吗只有收藏没有成交咋办
  4. unix黑客初学指导(转)
  5. 《开讲啦》 20160910 颜宁:女科学家去哪儿了?
  6. 树莓派串口与外部设备通信
  7. JavaWeb 文件的上传和下载
  8. 国内真正有技术开发能力的不足200人,区块链是否“只是一种传说”?
  9. iOS 调用私有函数安装app 卸载 app
  10. 大数据时代 书评及书摘