美文网首页
Spring 部分源码理解

Spring 部分源码理解

作者: eagle006 | 来源:发表于2022-12-05 22:20 被阅读0次

Spring 流程概述

入口 类 ClassPathXmlApplicationContext refresh()方法

容器刷新前的准备工作

<1> 设置容器启动时间

<2> 设置活跃状态为true

<3>设置关闭状态为false

<4> 获取Environment对象,并加载当前系统的属性值到Environment对象中

<5> 准备监听器和事件的集合对象,默认为空的集合

// Prepare this context for refreshing.prepareRefresh();

创建容器对象,DefaultListableBeanFactory,加载xml配置文件的属性值到当前工厂中,最重要的就是BeanDefinition

    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// Prepare the bean factory for use in this contextprepareBeanFactory(beanFactory);

// Allows post-processing of the bean factory in context subclassespostProcessBeanFactory(beanFactory);

// Invoke factory processors registered as beans in the contextinvokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creationregisterBeanPostProcessors(beanFactory);

// Initialize message source for this contextinitMessageSource();

// Initialize event multicaster for this contextinitApplicationEventMulticaster();

// Initialize other special beans in specific context subclassesonRefresh();

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

// Instantiate all remaining (non-lazy-init) singletons

finishBeanFactoryInitialization(beanFactory);

```

// Last step: publish corresponding eventfinishRefresh();

源码分析--spring启动流程细节

/*** 做容器刷新前的准备工作* 1、设置容器的启动时间* 2、设置活跃状态为true* 3、设置关闭状态为false* 4、获取Environment对象,并加载当前系统的属性值到Environment对象中* 5、准备监听器和事件的集合对象,默认为空的集合*/prepareRefresh();

prepareRefresh()方法关键片段:

// 留给子类覆盖,初始化属性资源  initPropertySources();// 创建并获取环境对象,验证需要的属性文件是否都已经放入环境中  getEnvironment().validateRequiredProperties();// 判断刷新前的应用程序监听器集合是否为空,如果为空,则将监听器添加到此集合中  if (this.earlyApplicationListeners == null) {      this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);  }else {// 如果不等于空,则清空集合元素对象    this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners);  }// 创建刷新前的监听事件集合  this.earlyApplicationEvents = new LinkedHashSet<>();

// 创建容器对象:DefaultListableBeanFactory// 加载xml配置文件的属性值到当前工厂中,最重要的就是BeanDefinitionConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

obtainFreshBeanFactory() 方法关键片段

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

源码分析--spring配置文件加载过程

接上一节obtainFreshBeanFactory方法

refreshBeanFactory方法:

loadBeanDefinitions方法

spring自定义标签解析过程

自定义标签步骤:

创建对应标签的解析类parser(对当前标签的其他属性值进行解析工作)

创建一个对应的解析器处理类(在init方法中添加自定义的parser类)

创建一个普通的spring.handlers配置文件,让应用程序能够完成加载工作

定义对应的schema和xsd文件

示例:

目录结构:

新建实体类User(略)

新建标签parser解析类 UserBeanDefinitionParser

新建对应的解析器处理类 UserNamespaceHandler

相关配置文件

在META-INF下新建对应的spring.handlers spring.schemas user.xsd文件

spirng.handlers 指定对应的handler处理类

spring.schemas 指定xsd文件路径

user.xsd xsd配置文件

关键方法:

getMergeLocalBeanDefinition在实例化之前,要把所有基础的BeanDefinition对象转换成RootBeanDefinition对象进行缓存,后续在需要马上实例化的时候直接获取定义的信息,而定义信息中如果包含了父类,那么必须要先创建父类才有子类。

BeanFacoryFacoryBean区别:  都是对象工厂,用来创建对象,如果使用BeanFactory接口,必须严格遵循Spring bean的生命周期, 从实例化到初始化,invokeAwareMethod, invokeInitMethod, before, after,此流程非常复杂且麻烦。 更加便捷简单的方式创建的话,用到了FactoryBean接口,不需要遵循此创建顺序。FactoryBean创建的对象由Spring管理,存在一级缓存,但是不是单例的话,需要每次调用的时候重新创建,缓存中不会保存当前对象。

Bean的生命周期

入口定义的xml或注解配置等

创建容器对象 obtainFreshBeanFactory

2.1 创建容器DefaultListableBeanFactory

2.2 设置某些属性值

2.3 加载配置文件 loadBeanDefinitions—>document  **—> ** element

—>parseDefaultElement(bean标签)/parseCustomElement(context/aop开头的标签,自定义标签等)

—>GenericBeanDefinition (后续调用才会触发) 合并—>RootBeanDefinition

prepareBeanFactory**—>** 给容器工厂设置某些属性值

invokeBeanFactoryPostProcessor**—>** 调用执行BFPP,可以修改或者引入其他的beanDefinition,需要注意BFPP      针对的操作对象是BeanFactory**—>** ConfigurationClassPostProcessor用来完成相关注解的解析工作(@Import,@Configuration,@Component,@Bean等等)

registerBeanPostProcessor 实例化BPP**—>** 完成BeanPostProcessor的注册工作,方便后续在实例化完成之后调用before和after的操作

finishBeanFactoryInitialization—>完成对象的创建工作 (先从缓存中找,没有则创建)—>将需要创建的bean对象放到数组中,挨个进行创建

getBean**—>**doGetBean **—>**createBean **—>**doCreateBean

**—>**createBeanInstance(1. supplier 2. factoryMethod 3. 反射创建 4. BPP代理方式)

    **—>**applyMergedBeanDefinitionPostProcessors

    (注册生命周期接口 @PostConstruct,@PreDestory,@Resource,@Autowired,@Value)

—>populateBean(1.填充属性 2.创建需要依赖的bean对象)

—>initiializeBean(进行初始化工作

invokeAwareMethod(BeanNameAware, BeanClassLoaderAware,BeanFactoryAware)

执行BPP的before方法 ApplicationAwarePostProcessor继续实现某些Aware接口的set方法/CommonAnnotationBeanPostProcessor

invokeInitMethod 判断是否实现InitializingBean 执行afterPropertiesSet 最后一次修改属性值

/执行用户自定义的init-method

执行BPP的after方法 aop)

—>获取对象来进行相关操作**—>** 销毁流程 DestructionAwareBeanPostProcessors(postProcessBeforeDestruction) / DisposableBean

/ 自定义的destoryMethod

循环依赖

Spring AOP的BeanDefinition的准备工作

使用xml注解

查看配置文件的解析工作,在处理之后的BeanDefinition中包含什么信息

BeanDefinition的解析工作(loadBeandefinitions(default和custom))

对aop相关的BeanDefinition进行实例化操作,在进行第一个对象创建之前,就必须要把aop相关的对象提前准备好,因为无法预估哪些对象需要动态代理

在哪个步骤中可以提前实例化并且生成对应的对象

BFPP是用来对BeanFactory进行修改操作的,不会影响到后续的实例化过程

BPP(BeanPostProcessor(before和after))  resolveBeforeInstantiation()

AspectJPointcutAdvisor#0->AspectJAroundAdvice->MethodLocatingFactory 0 / 表达式 1 / SimpleBeanFactoryAwareAspectInstanceFactory 2

AspectJPointcutAdvisor#1->AspectJMethodBeforeAdvice->MethodLocatingFactory 0 / 表达式 1 / SimpleBeanFactoryAwareAspectInstanceFactory 2

AspectJPointcutAdvisor#2->AspectJAfterAdvice->MethodLocatingFactory 0 / 表达式 1 / SimpleBeanFactoryAwareAspectInstanceFactory 2

AspectJPointcutAdvisor#3->AspectJAfterReturingAdvice->MethodLocatingFactory 0 / 表达式 1 / SimpleBeanFactoryAwareAspectInstanceFactory 2

AspectJPointcutAdvisor#4->AspectJAfterThrowingAdvice->MethodLocatingFactory 0 / 表达式 1 / SimpleBeanFactoryAwareAspectInstanceFactory 2

总结

准备BeanDefinition->1.AspectjExpressionPointcut  2.Advisior#0 - #4  3. AspectjAutoProxyCreator

Spring AOP的核心对象的创建

创建AspectJPointcutAdvisor#0-4, 先使用带参的构造方法进行对象的创建,但是想使用带参的构造方法必须要参数对象准备好,因此要准备创建包含的对象AspectJAroundAdvice

创建AspectJAroundAdvice,也需要使用带参的构造方法进行创建,也需要提前准备好具体的参数对象,包含三个参数: MethodLocatingFactoryBean, AspectJExpressionPointcut, SimpleBeanFactoryAwareAspectInstanceFactory

分别创建上述的三个对象,上述三个对象的创建过程都是调用无参的构造方法,直接反射生成。

相关文章

网友评论

      本文标题:Spring 部分源码理解

      本文链接:https://www.haomeiwen.com/subject/yhamwxtx.html