当你的才华还撑不起你的野心的时候,唯有静下心来学习。

spring运行流程图(https://www.processon.com/view/5f3fcab8e0b34d07118258cb?fromnew=1)

1. 简介

在研究spring源码之前,首先要确保自身有使用过spring框架开发过项目,有一定的基础知识,比如知道什么是beanFactory、Ioc、依赖注入等,并且简单知道原理最好。由于spring源码体系庞大,无法做到涉及到每一个方面细节,只能讲解他的核心功能,一个章节也无法全部概述,可能会分多个章节。在读spring源码的过程中,如果只是单纯的看并不会有太大的收获,还是需要自己手动调式源码。本章是基于注解方式(AnnotationConfigApplicationContext)进行解读的。编写测试用例来模拟spring加载流程,当了解了spring的工作流程在谈他的如何进行融会贯的。
       一定要自己对着源码读,切记在读源码的过程中,不要死扣细节,要使用面向对象的思想来解读,只需要知道这段代码为我们做了什么就可以了,如果想深入了解,可以自己点进去深入研究,要不然代码段太长,容易绕晕不容易读下去。
       以一个项目为例,看spring是如何进行工作的,结构如下,随便使用一个spring项目就可以,并没有太大影响:

       编写一个测试类,进行spring加载:

@Configuration
@ComponentScan("com.online.manager")
public class TestController {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestController.class);// TODO1 到这一步spring已经加载完成UserController userController = context.getBean(UserController.class);}
}

当测试执行到context.getBean的时候,spring容器已经加载完成了,所有我们需要查看new AnnotationConfigApplicationContext底层做了什么。当点击进入到AnnotationConfigApplicationContext类中(ctrl + 鼠标)的时候,我们进入的是这个构造方法:

 public AnnotationConfigApplicationContext(Class... annotatedClasses) {// this 是调用自身的无参构造方法, 点进行查看// 本章节只讲这个this做了什么,不要看他简单,其实很深this();// 下一次讲register(annotatedClasses);refresh();}

可以看见第一行代码this();他调用的是自身的无参构造方法,由于java特性知道在调用自身的无参构造方法,会先调用父类的无参构造方法,所以我们先进入他的父类(GenericApplicationContext)中查看他的无参构造。

GenericApplicationContext无参构造方法:

 // 父类的这个属性非常重要,他就是spring的工厂private final DefaultListableBeanFactory beanFactory;public GenericApplicationContext() {this.customClassLoader = false;this.refreshed = new AtomicBoolean();// 在父类构造方法中初始化工厂 (很重要)this.beanFactory = new DefaultListableBeanFactory();}

GenericApplicationContext的类中,可以看到他有一个非常重要的属性,就是我们常说的bean工厂beanFactory,想看他的属性自己点进去查看,查看他有哪些属性。他的构造方法进行实例化了spring工厂(只是创建但并没有初始化)。这就是beanFactory的真身,如果想深入了解可以继续查找GenericApplicationContext的父类为我们做了什么工作,这里就不在概述了。

基于继承关系,AnnotationConfigApplicationContext类持有了这个beanFactory的实例,很重要。父类的构造方法执行完了,接下来看自己的构造方法。(不要绕晕了)

AnnotationConfigApplicationContext无参构造方法:

 public AnnotationConfigApplicationContext() {// 把自身的实例传递给他的构造方法,创建了一个注解bean定义读取器,用来把我们的配置类解析成BeanDefinition。很重要this.reader = new AnnotatedBeanDefinitionReader(this);// 创建一个bean定义扫描器,在外部手动调用的,使用scan方法进行扫描,不重要可调过this.scanner = new ClassPathBeanDefinitionScanner(this);}

AnnotationConfigApplicationContext的构造方法通过把自身实例(this)传过去调用AnnotatedBeanDefinitionReader的构造方法创建一个注解bean定义读取器,作用用来把我们的配置类解析成BeanDefinition放入到beanFactory的beanDefinitionMap属性中。

为什么要报this传过去呢?可以思考一下?
       因为这个this是AnnotationConfigApplicationContext的实例,而因为他父类的关系,所以他自己持有了bean工厂的实例。因此可以通过过来的this获取到我们的beanFactory工厂。

但是在AnnotatedBeanDefinitionReader(this)的这个构造方法里帮我们做了很多的事情,这里面代码非常的重要,主要是完成beanFactory工厂的首次初始化工作,往下看。

AnnotatedBeanDefinitionReader(this)构造方法:

 public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {this(registry, getOrCreateEnvironment(registry));}// 最终调用的构造方法public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {..... 不太重要的代码省略, 主要完成初始化// 很重要 -- 完成`beanFactory`工厂的首次初始化工作AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);}

可以看到上面的这个BeanDefinitionRegistry registry参数的实际上就是我们的AnnotationConfigApplicationContext实现(可以通过查看类关系,AnnotationConfigApplicationContextBeanDefinitionRegistry的一种实现),最终会调用registerAnnotationConfigProcessors这个方法。

registerAnnotationConfigProcessors方法(很重要):

 public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {registerAnnotationConfigProcessors(registry, (Object)null);}// 最终调用这个方法public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {// 在这个方法里,从registry里获取我们的bean工厂,细节可以自己点进去查看(ctrl + 点击方法)// 实现是 把registry强转为GenericApplicationContext,调用他的getDefaultListableBeanFactory获取工厂DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);// 在之前工厂就已经创建好了,肯定不为空// 下面代码就是bean工厂的初始化工作了,只需要知道为我们工厂填充了这些属性,为了之后使用这些功能if (beanFactory != null) {if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {// 添加了比较器用于排序,(处理Ordered接口、PriorityOrdered接口功能)beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);}if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {// 提供延迟加载的功能beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());}}Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet(8);RootBeanDefinition def;// 向工厂注册的7个后置处理器非常重要也是完成spring的核心功能if (!registry.containsBeanDefinition("org.springframework.context.annotation.internalConfigurationAnnotationProcessor")) {def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);def.setSource(source);// 向beanDefinitionMap加入ConfigurationClassPostProcessor后置处理器// 他实现的是BeanDefinitionRegistryPostProcessor接口// 主要完成自定义类(@Configuration、@Componet、@Serveice、@Import注解)的扫描,把我们定义的类加入到spring容器中// 后面会在使用的时候会详细介绍beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"));}if (!registry.containsBeanDefinition("org.springframework.context.annotation.internalAutowiredAnnotationProcessor")) {def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);def.setSource(source);// 向beanDefinitionMap加入AutowiredAnnotationBeanPostProcessor后置处理器// 他实现的是BeanFactoryPostProcessor接口, 处理@Autowired,完成bean的属性注入的工作beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"));}// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);def.setSource(source);// 向beanDefinitionMap加入CommonAnnotationBeanPostProcessor后置处理器// 他实现的是BeanFactoryPostProcessor接口, 处理@Resource和JSR 250注解beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));}//jpa功能if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition();try {def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,AnnotationConfigUtils.class.getClassLoader()));}catch (ClassNotFoundException ex) {throw new IllegalStateException("Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);}def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));}if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);def.setSource(source);// 注入事件监听方法beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));}if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);def.setSource(source);// 注入默认事件监听工厂beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));}return beanDefs;}

registerAnnotationConfigProcessors这个方法很重要,完成beanFactory的初始化工作,向beanDefinitionMap中注册了7个后置处理器的BeanDefinition的信息,其中ConfigurationClassPostProcessorAutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor这三个后置处理器非常的重要,其中ConfigurationClassPostProcessor这个后置处理器是重中之重,后续使用的时候会进行讲解,这是只是想beanFactory中进行设置,但并没有使用,方便在后续时候过程中不知道他是如何产生的。

到这里AnnotationConfigApplicationContext的无参构造方法里的new AnnotatedBeanDefinitionReader(this)这行代码就执行结束了。该执行new ClassPathBeanDefinitionScanner(this)这段代码了,其实这段代码的用处不是很大,主要是提供外部也就是程序员自己在外部使用的,不重要,感兴趣的话可以自己点进去查看。

到这里AnnotationConfigApplicationContext的构造方法里的this()方法就执行结束了,其中有很多细节的地方没有讲述清楚,可以的话可以自己进行查看。

Spring源码篇一之beanFactory的真身和6大后置处理器的注册相关推荐

  1. 第五篇:Spring源码篇-ApplicationContext

    Spring源码篇-ApplicationContext   前面通过手写IoC,DI.AOP和Bean的配置.到最后ApplicationContext的门面处理,对于Spring相关的核心概念应该 ...

  2. spring源码:九大后置处理器

    目的: spring在完成一个bean的初始化.实例化的过程中,会用到九个后置处理器:本文梳理出这九个后置处理器 九大后置处理器 spring在初始化的过程中,会在九个地方分别调用了五个后置处理的九个 ...

  3. 【06】Spring源码-分析篇-ApplicationContext

    Spring源码篇-ApplicationContext   前面通过手写IoC,DI.AOP和Bean的配置.到最后ApplicationContext的门面处理,对于Spring相关的核心概念应该 ...

  4. Spring源码系列(十二)Spring创建Bean的过程(二)

    1.写在前面 上篇博客主要Spring在创建Bean的时候,第一次调用的Bean的后置处理器的过程,同时笔者也打算将整个Spring创建的Bean的过程,通过这个系列,将Bean的创建过程给讲清楚,废 ...

  5. Spring源码学习(三)-- 底层架构核心概念解析

    前面,我们大概了解了Spring中的一些概念和底层工作流程,这篇是后续看Spring源码所必备的,防止后续看源码的过程中,遇到不会的概念得单独跳出来学习.​ BeanDefinition BeanDe ...

  6. spring源码分析第三天------spring核心IOC容器和依赖注入原理

    基于XML的依赖注入 1.依赖注入发生的时间 当 Spring IOC 容器完成了 Bean 定义资源的定位.载入和解析注册以后,IOC 容器中已经管理类 Bean 定义的相关数据,但是此时 IOC ...

  7. 从Spring源码探究AOP代码织入的过程

    随着不断地使用Spring,以及后续的Boot.cloud,不断的体会到这个拯救Java的生态体系的强大,也使我对于这个框架有了极大的好奇心,以至于产生了我为什么不能写一个这样的框架的思考. 通过自学 ...

  8. Spring源码分析(二):底层架构核心概念解析

    本节主要介绍一下Spring底层中用到的"基础设施",是后续看Spring源码所必备的,防止后续看源码的过程中,遇到不会的概念得单独跳出来学习. BeanDefinition Be ...

  9. Spring源码分析(二)BeanFactoryPostProcessor之ConfigurationClassPostProcessor的调用过程

    前言:BeanFactoryPostProcessor是Spring中的重要组成接口,容器创建过程中起到解析注解,注册BeanDifinition,改变BeanDefiniton属性(也就是改变bea ...

最新文章

  1. html5简单拖拽实现自动左右贴边+幸运大转盘
  2. Win7 64位系统上配置使用32位的Eclipse
  3. 三个管脚的压电陶瓷片
  4. js 运算符 || 妙用
  5. sqlplus执行SQL文件
  6. 分享一道阿里Java并发面试题 (详细分析篇)
  7. 深度学习总结:用pytorch做dropout和Batch Normalization时需要注意的地方,用tensorflow做dropout和BN时需要注意的地方,
  8. JSP 中EL表达式用法详解
  9. linux_base-f10-10_7 linuxulator is not (kld)loaded
  10. MFC序列化(serial)简单例子
  11. linux每个版本发布时间,Ubuntu 21.04各版本的发布时间公布和计划功能介绍
  12. 【例题+习题】【数值计算方法复习】【湘潭大学】(一)
  13. 深入理解Date对象
  14. 2015C蓝桥杯C++A:格子中输出(详细讲解)
  15. php简单多态,PHP 对象 多态性 简单图形计算器
  16. 学习笔记之正则表达式
  17. python快速入门神器 知乎_Python爬虫偷懒神器!快速一键生成Python爬虫请求头
  18. 一个好玩的小游戏(纯C语言编写)
  19. 国外图片分享网站有哪些?20个国外免费、高清图片素材网站、图库全合集
  20. 2014Esri全球用户大会之Developer

热门文章

  1. Python筛选EXCEL数据
  2. 奇瑞QQ冰淇淋,成功俘获女孩子芳心
  3. Bootstrap框架快速上手攻略
  4. 计算机关闭网络发现还可以共享打印机吗,打印机不能共享或启用网络发现被自动关闭...
  5. ESXi 6.5 虚拟机直通K80显卡并安装NVIDIA显卡驱动:
  6. 最小公倍数(C++)
  7. android pc98,pc98模拟器forandroi
  8. 手机开蓝牙会不会被别人连上_不连蓝牙就能扩音的小音箱,你见过吗?
  9. wordpress代码块不显示$字符
  10. [论文阅读]SofGAN: A Portrait Image Generator with Dynamic Styling