spring生命周期 & 容器启动过程
2022-04-15 10:06:47 5 举报
AI智能生成
spring从起的初始化和启动过程详解,吐血整理,一图在手打败天下无敌手
作者其他创作
大纲/内容
初始化SpringContext<br>refresh方法前<br>
ApplicationContextInitializer.initialize<br>springBoot的主要几种实现有<br>
1.DelegatingApplicationContextInitializer<br> 这个类可以从环境中读取<b style=""><font color="#ff0000">context.initializer.classes</font></b>配置的类,进行监听<br> 的触发<br>
2.ContextIdApplicationContextInitializer<br> 获取contextid并注册到容器中(项目名)
3.SharedMetadataReaderFactoryContextInitializer<br> 添加了<font color="#ff0000"><b>CachingMetadataReaderFactoryPostProcessor</b></font>
Context初始化完成<br>开始刷新容器
AbstractApplicationContext.refresh
prepareBeanfactory<br>准备beanFactory
为BeanFactory添加高优先级的BeanFactoryPostProcessor
1.添加<font color="#ff0000"><b>ApplicationContextAwareProcessor</b></font>
2.添加<font color="#ff0000"><b>ApplicationListenerDetector</b></font>
注册了Bean
<font color="#000000">1</font><b style="color: rgb(255, 0, 0);">.environment-</b><font color="#000000">日志参数</font><b style="color: rgb(255, 0, 0);">、springprofile、propertySource</b>
2.<font color="#ff0000"><b>systemProperties</b></font> - java相关的参数
3.<font color="#ff0000"><b>systemEnvironment</b></font>-系统参数路径等
postProcessBeanFactory<br>这个是抽象方法<br>
子类<font color="#ff0000"><b>ServletWebServerApplicationContext</b></font>是<b><font color="#ff0000">AnnotationConfigServletWebServerApplicationContext</font></b>的父类<br> 主要是添加了<b><font color="#ff0000">WebApplicationContextServletContextAwareProcessor</font></b>(beanFactory.addBeanPostProcessor)
applicationContext目前有几种主要实现<br>1.AnnotationConfigServletWebServerApplicationContext-springboot启动后会创建该容器<br>2.AnnotationConfigApplicationContext<br><br>
触发BeanFactoryPostProcessor生命周期方法
invokeBeanFactoryPostProcessors<br> 这一步是触发所有的BeanFactory的生命周期方法<br>
1.执行<font color="#ff0000"><b>BeanDefinitionRegistry</b></font>接口
执行方法<b><font color="#ff0000">postProcessBeanDefinitionRegistry</font></b><br>这个方法发生在所有的内部的bean定义被加载后<br> (比如之前生命周期方法中加入的各种Processor),<br>可以对已经加载的bean进行修改和新增bean的定义<br>
第一步:调用通过context的addBeanFactoryPostProcessor添加的BeanDefinitionRegistry的方法postProcessBeanDefinitionRegistry
第二步:从beanFactory中获取即实现了<b><font color="#ff0000">BeanDefinitionRegistryPostProcessor</font></b>又实现了<font color="#ff0000"><b>PriorityOrdered</b></font>的Processor<br>,排序后调用但是晚于通过context的addBeanFactoryPostProcessor添加的
第三步:从beanFactory中获取即实现了<b><font color="#ff0000">BeanDefinitionRegistryPostProcessor</font></b>又实现了<b><font color="#ff0000">Ordered</font></b>的Processor,排序后依次调用
第四步:由于BeanDefinitionRegistryPostProcessor注册的bean可能还包含BeanDefinitionRegistryPostProcessor,所以需要循环检查,并且排序依次调用postProcessBeanDefinitionRegistry,直到没有BeanDefinitionRegistryPostProcessor为止
2.执行<b><font color="#ff0000">BeanFactoryPostProcessor</font></b>接口
执行方法<b><font color="#ff0000">postProcessBeanFactory</font></b>
第一步:调用既实现了<b style="color: rgb(255, 0, 0);">BeanDefinitionRegistryPostProcessor</b><font color="#000000">又实现了</font>BeanFactoryPostProcessor<br>的<b><font color="#ff0000">postProcessBeanFactory</font></b>方法调用顺序同<b><font color="#ff0000">postProcessBeanDefinitionRegistry</font></b>的逻辑<br>
比如 ConfigurationClassPostProcessor在这个环节被调用,<br>会将带有@Configuration的类增强,生成代理类并替换掉bean定义中的class<br>这个环节也可以增加BeanPostProcessor<br>
第二步:最后调用非BeanDefinitionRegistryPostProcessor的<b><font color="#ff0000">postProcessBeanFactory<br></font></b>调用顺序的逻辑同上
第三步:再处理前两步中可能再次产生的BeanFactoryProcessor,也是按照PriorityOrdered ,Ordered 和非排序要求的processor 依次调用<br>通过查看源码,普通的BeanFactoryProcessor的<font color="#ff0000"><b>postProcessBeanFactory</b></font>中再注册BeanFactoryProcessor时可以生效,如果下一层再注册会被忽略(不然死循环了)
注册beanPostProcessor
和调用一样,根据PriorityOrdered、内部processor(MergedBeanDefinitionPostProcessor)、Ordered和非Ordered<br>将beanPostProcessor分组(内部和PriorityOrdered可重复) <br>最终通过beanFactory.addBeanPostProcessor注册processor<br>注册顺序为 PriorityOrdered -> Ordered -> 普通的 -> MergedBeanDefinitionPostProcessor<br>如果addBeanPostProcessor时,beanFactory中已经存在了,则移除,然后添加至list的末尾
AutowiredAnnotationBeanPostProcessor
注册监听器
和执行BeanFactory一样,优先注册abstractApplicationContext中存在的监听然后<br>添加beanFactory容器中所有类型为ApplicationListener的监听bean(<font color="#ff0000"><b>不支持Ordered接口</b></font>)<br>
初始化所有的单例bean<br>
1.执行InstantiationAwareBeanPostProcessor接口
执行<b><font color="#ff0000">postProcessBeforeInstantiation</font></b><br>如果实现接口的方法postProcessBeforeInstantiation返回对应的bean实例<br>那么就跳过创建bean的过程(用实现类返回的bean,不需要调用构造创建了)<br>
<font color="#f44336"><b>InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation</b></font>
spring其中之一内置的实现<br>1.AnnotationAwareAspectJAutoProxyCreator<br> 这个会在此创建代理类对象<br><br>
2.执行SmartInstantiationAwareBeanPostProcessor接口
如果实现了该接口的方法<font color="#ff0000"><b>determineCandidateConstructors</b></font>能够返回构造函数<br>则使用返回的构造函数来创建bean对象
1.AutowiredAnnotationBeanPostProcessor<br>该类实现接口,用来实现<b><font color="#ff0000">@Lookup,封装mehtodOverride元数据放入</font></b>BeanDefinition<font color="#000000" style="">中为后期的方法覆盖准备</font><br>Lookup作用:通常用在一个单例的bean注入一个非单例的bean时候,<br>一旦注入了非单例的bean也变得单例了,所以会定义一个返回非单例bean方法,在方法上面加上Lookup注解,<br>在调用方法的时候spring会自动每次从容器中进行getBean,实现非单例的逻辑,基本原理就是代理类覆盖含有lookUp的方法<br>会在determineCandidateConstructors中将beanDefinition 中的overrideMethod中加入此方法<br>
3.执行MergedBeanDefinitionPostProcessor接口
调用bean的构造方法创建出来bean后会触发方法<font color="#ff0000"><b>postProcessMergedBeanDefinition</b></font><br><br>
1.CommonAnnotationBeanPostProcessor<br> 该类实现JSR-250、WebServiceRef、EJB 3中的注解比如<br> PostConstruct、PreDestroy(这两个通过继承InitDestroyAnnotationBeanPostProcessor实现)、<br> Resource、WebServiceRef 这个类主要是构建ResourceMetadata(处理Resource、WebServiceRef,EJB)<br>
2.InitDestroyAnnotationBeanPostProcessor<br> 实现bean的PostConstruct、PreDestroy 这两个环节元数据的构建,放入Processor的缓存中
3.AutowiredAnnotationBeanPostProcessor<br> 处理@Autowired、@Value、 @Inject(JSR-330)、@Lookup
4.执行InstantiationAwareBeanPostProcessor接口
执行接口的方法<b><font color="#ff0000">postProcessAfterInstantiation</font></b>
实现该接口的类有<br>
执行接口的方法<font color="#ff0000"><b>postProcessProperties<br><br></b></font><br>
1.AutowiredAnnotationBeanPostProcessor<br> 执行autowired和value注解的注入
2.执行SmartInstantiationAwareBeanPostProcessor的<b><font color="#ff0000">getEarlyBeanReference</font></b><br>如果有循环依赖问题,可以返回替代早期对象的对象
AbstractAutoProxyCreator类实现了该接口<br>在执行getEarlyBeanReference时能够生成代理类,注入到依赖的bean中
applyPropertyValues
5.执行Aware接口
1.BeanNameAware<br>
2.BeanClassLoaderAware
3.BeanFactoryAware
6.执行BeanPostProcessor接口
执行接口方法<font color="#ff0000"><b>postProcessBeforeInitialization<br></b></font>初始化之前(区别于实例化)
实现的类有<br>1.ApplicationContextAwareProcessor<br> Application自己实现了触发Aware的其他接口
1.EnvironmentAware<br> 设置容器的environment
2.EmbeddedValueResolverAware<br> 获取spring的内置的解析器,用来解析配置文件的内容如:${maodou.service}
3.ResourceLoaderAware<br> 获取ResourceLoader用来获取spring加载的resource
4.ApplicationEventPublisherAware<br> 事件的发布器
5.MessageSourceAware
6.ApplicationContextAware
2.ServletContextAwareProcessor<br>用来设置ServletContext和ServletConfigAware
3.ConfigurationClassPostProcessor<br> 如果一个bean实现了接口<b><font color="#ff0000">ImportAware</font></b>,并且由@Import进行注册的bean,那么会注入导入这个bean的配置类的所有注解元数据信息<br> 这个类中获取ImportRegistry来实现获取元注解信息<br>
4.ConfigurationPropertiesBindingPostProcessor<br> 将被注解ConfigurationProperties的类绑定PropertySources<br> 即将配置文件中的值注入到类中,比如我们的XXXHttp类
5.InitDestroyAnnotationBeanPostProcessor<br> 调用<font color="#ff0000"><b>PostConstruct</b></font>方法
7.执行InitializingBean接口
执行方法<font color="#ff0000"><b>afterPropertiesSet</b></font>
执行<font color="#ff0000"><b>init-method</b></font><br>xml方式指定的init-method
8.执行BeanPostProcessor接口
执行接口方法<font color="#ff0000"><b>postProcessAfterInitialization<br></b></font>初始化之前(区别于实例化)
1.AsyncAnnotationBeanPostProcessor<br> 主要是实现代理增强,添加Advisor
2.DistributedLockAopBeanPostProcessor<br> 我们自己实现的分布式锁也在在这个期间进行动态织入
3.SchedulerProxyScheduledLockAopBeanPostProcessor<br> 开源项目 shedlock 也是在这个期间动态织入的
4.PersistenceExceptionTranslationPostProcessor<br>事务实现
5.ScheduledAnnotationBeanPostProcessor<br>spring的任务调度
6.AbstractAdvisorAutoProxyCreator,用来对目标bean进行代理<br>比如某bean的方法使用了事务注解,通过该类创建目标bean的代理对象,并添加调用拦截
9.registerDisposableBean<br> 注册销毁bean的handler
单例Bean <b><font color="#ff0000">registerDisposableBean</font></b>
充分条件1:实现了DisposableBean
充分条件2:实现了AutoCloseable
充分条件3:通过@Bean注册,没有指定destroyMethod,但bean有名字为close或shutdown方法
充分条件4:通过@Bean注册,指定了destroyMethod
充分条件5:有DestructionAwareBeanPostProcessor并且requiresDestruction返回true<br>
prototype不注册销毁事件
其他的<b><font color="#ff0000">registerDestructionCallback</font></b>
0 条评论
下一页