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();
/*** 做容器刷新前的准备工作* 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();
接上一节obtainFreshBeanFactory方法
refreshBeanFactory方法:
loadBeanDefinitions方法
自定义标签步骤:
创建对应标签的解析类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对象进行缓存,后续在需要马上实例化的时候直接获取定义的信息,而定义信息中如果包含了父类,那么必须要先创建父类才有子类。
BeanFacory和FacoryBean区别: 都是对象工厂,用来创建对象,如果使用BeanFactory接口,必须严格遵循Spring bean的生命周期, 从实例化到初始化,invokeAwareMethod, invokeInitMethod, before, after,此流程非常复杂且麻烦。 更加便捷简单的方式创建的话,用到了FactoryBean接口,不需要遵循此创建顺序。FactoryBean创建的对象由Spring管理,存在一级缓存,但是不是单例的话,需要每次调用的时候重新创建,缓存中不会保存当前对象。
入口定义的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的准备工作
查看配置文件的解析工作,在处理之后的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
创建AspectJPointcutAdvisor#0-4, 先使用带参的构造方法进行对象的创建,但是想使用带参的构造方法必须要参数对象准备好,因此要准备创建包含的对象AspectJAroundAdvice
创建AspectJAroundAdvice,也需要使用带参的构造方法进行创建,也需要提前准备好具体的参数对象,包含三个参数: MethodLocatingFactoryBean, AspectJExpressionPointcut, SimpleBeanFactoryAwareAspectInstanceFactory
分别创建上述的三个对象,上述三个对象的创建过程都是调用无参的构造方法,直接反射生成。