Spring之ApplicationContext#refresh启动全部流程

    科技2022-08-25  100

    1:prepareRefresh

    主要是做一些环境上的准备。 清理scanner的缓存。把容器状态切换为active。在上下文环境中初始化任何占位符属性源。验证标记为所需的所有属性是否可解析。存储预刷新ApplicationListeners。Allow for the collection of early ApplicationEvents。

    2:obtainFreshBeanFactory

    告诉子类刷新内部bean工厂,主要是设置了serializationId=“allication”。并且拿到BeanFactory,默认是DefaultListableBeanFactory。

    3:prepareBeanFactory

    准备BeanFactory以供在此上下文中使用。配置工厂的标准上下文特性,例如上下文的类加载器和后处理器。加入ApplicationContextAwareProcessor,注册一些ResolvableDependency。

    4:postProcessBeanFactory

    允许在上下文子类中对bean工厂进行后处理。比如增加一些beanPostProcessor。

    5:invokeBeanFactoryPostProcessors

    调用ApplicationContext的BeanFactoryPostProcessor。ConfigurationClassPostProcessor:负责BeanDefinition的注册。 先找到拿到主配置类的BeanDefinition,以主配置类上的**@SpringBootApplication**注解为入口,加载所有Bean的BeanDefination。实例化一个ConfigurationClassParser,这个类会负责加载带有相关注解的类的ConfigurationClass,和spring.factories里需要加载的BeanDefinition(比如和自动配置相关的类)。首先解析主启动类,会把主启动类的AnnotationMetadata封装为一个ConfigClass。首先会递归地处理配置类及其超类层次结构,比如此配置有个嵌套配置类(或者又套了很多层配置类),会先递归处理这些嵌套配置类,最外层的类是最后处理的在处理配置类(注意:这里的配置类只要加了**@Component都算配置类,不一定得加@Configuration**)时: 处理所有的**@PropertySource**。处理所有的**@ComponentScan**。在进行扫描时,会进一步的处理扫描出的BeanDefinition,必要时会进行递归。比如A上有个@ComponentScan,A扫描出了B,C。此时会先处理B和C(处理@PropertySource,@ComponentScan,@Import等注解),假如B上又有@ComponentScan,又会进行扫描。处理所有的**@Import**。处理所有的**@ImportResource**。将所有带**@Bean注解的方法封装为BeanMethod加入到ConfigurationClass的beanMethods**字段中。处理接口的默认方法。处理父类。最后执行deferredImportSelectorHandler.process(),比如会执行AutoConfigurationImportSelector,此类会扫描MATE-INF下的spring.factories下的所有相关的自动配置类,然后放在ConfigurationClassParser里的configurationClasses里。上面所有处理出的ConfigurationClass都会放在ConfigurationClassParser里的configurationClasses里。 之后实例化一个ConfigurationClassBeanDefinitionReader负责读取上一步读取出的所有ConfigurationClass,然后根据其内容创建BeanDefinition。此步骤会为@Bean注解的方法注册BeanDefination。 调用PropertySourcesPlaceholderConfigurer的postProcessBeanFactory来处理**@Value**里的占位符号。调用EventListenerMethodProcessor(此类负责将@EventListener注解标注的方法注册为ApplicationListener实例)的postProcessBeanFactory为EventListenerMethodProcessor设置eventListenerFactories。

    6:registerBeanPostProcessors

    实例化并注册所有BeanPostProcessor bean 会通过getBeanNamesForType来查询所有满足条件的beanDefibition的beanName。首先,注册实现PriorityOrdered的beanPostProcessor。接下来,注册实现Ordered的beanPostProcessor。现在,注册所有常规的BeanPostProcessor。最后,重新注册所有内部beanPostProcessor。最最后,将用于检测内部bean的后处理器重新注册为应用程序侦听器,将其移动到处理器链的末端(用于获取代理等)。

    7:initMessageSource

    先从容器中查找是否有beanName为messageSource的BeanDefinition,有则使用容器中的,没有则使用DelegatingMessageSource,此类是一个空的{@link MessageSource},它将所有调用委托给父MessageSource。如果没有父级可用,它将无法解析任何消息。

    8:initApplicationEventMulticaster

    初始化ApplicationEventMulticaster。如果上下文中没有定义,则使用SimpleApplicationEventMulticaster。

    9:onRefresh

    初始化主题功能。

    创建WebServer(这里是在webApplicationType为Servlet的情况下)。

    先获取用于创建嵌入式WebServer的ServletWebServerFactory。此步骤会从容器中获取类型为ServletWebServerFactory的所有BeanName,如果获取不到或者获取了多个,都会抛出异常,之后通过获取到的beanName去getBean,就得到了一个TomcatServletWebServerFactory。然后会通过这个工厂获取一个WebServer。 实例化一个Tomcat对象。设置Tomcat的baseDir,Tomcat要求设置基目录,因为许多其他位置(例如工作目录)的默认值都是从基目录派生的。这应该是第一个调用的方法。实例化一个Connector[HTTP/1.1-auto-1],此内部的ProtocolHandler(网络传输协议)为Http11NioProtocol。获取Tomcat的Service,没有Server则会实例化一个StandardServer(Server的一个标准实现)。设置Server的setCatalinaBase和setCatalinaHome。再实例化一个StandardService,将此Service添加到Server中。返回Server。再从返回的Server中寻找到Sever中的services下标为0的Service,把上一步实例化的Connector添加到这个Service中。定制Connector,设置端口号,设置URIEncoding(UTF-8),调用所有的tomcatConnectorCustomizers,定制connector,主要是设置connector中的协议。 设置最大线程数(默认:200)。设置最小线程数(默认:10)。设置最大HttpHeaderSize(默认:8K)。设置可吞下的请求正文(RequestBody)的最大数量(默认:2M)。设置容器将自动解析的POST的最大大小(默认:2M)。设置最大连接数(8192)。设置允许服务器开发人员指定应用于服务器套接字的acceptCount(backlog)。默认情况下,此值为100。设置将保留在高速缓存中并与后续请求一起重新使用的最大空闲处理器数。默认值为200。值-1表示无限制。 设置此主机的自动部署标志值为false。配置Engine,需要先获取Engine(StandarEngine)。给Tomcat的Servie添加additionalTomcatConnectors。准备Tomcat上下文。实例化一个TomcatWebServer。 设置此TomcatWebServer的Tomcat为前面创建好的Tomcat,设置autoStart为true。startDaemonAwaitThread,使得Tomcat一直监听指定端口。

    10:registerListeners

    检查侦听器bean并注册它们。 首先注册静态指定的侦听器。getApplicationEventMulticaster().addApplicationListener(listener);注册还未初始化的BeanName。getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);发布所有的早期事件。getApplicationEventMulticaster().multicastEvent(earlyEvent);

    11:finishBeanFactoryInitialization

    实例化所有剩余的(非延迟初始化)单例。主要有: 允许缓存所有bean定义元数据,而不期望进一步的更改。既之后会启用allBeanNamesByType,singletonBeanNamesByType这2个Map。实例化所有剩余的(非延迟初始化)单例。遍历所有的beanDefinitionNames,getMergedLocalBeanDefinition(beanName)。 首先mergedBeanDefinitions.get(beanName),获取不到再调用getMergedBeanDefinition(beanName, getBeanDefinition(beanName))将传入的BeanDefinition转化为RootBeanDefinition,然后放入mergedBeanDefinitions中,再返回。 拿到上一步返回的RootBeanDefinition,判断此bean是否能被创建。确认可以创建后走AbstractBeanFactory的doGetBean。将传入的beanName(可能为别名,FactoryBean名)转化为规范的beanName。检查DefaultSingletonBeanRegistry中是否有手动注册的单例。通过正规的beanName得到MergedBeanDefinition,然后检查这个bean定义。检查当前bean的dependOn。(感觉这一步是是在处理一些阴间的东西,可以不用管)创建Bean。进入DefaultSingletonBeanRegistry的getSingleton方法。将此beanName放入singletonsCurrentlyInCreation中。进入到创建bean的过程: 进入到AbstractAutowireCapableBeanFactory的creatBean方法。调用resolveBeforeInstantiation,主要是调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation和postProcessAfterInstantiation,其中会调用和AOP相关的AnnotationAwareAspectjAutoProxyCreator这个类,尝试在bean实例化前返回一个bean的代理,而不用去实例化bean。如果这一步成功实例化了一个bean,就不会走下面的步骤。进入到doCreateBean方法。会先createBeanInstance,这个方法里会选择适合的构造函数来实例化bean,如果构造器有参数,还会解析参数,然后实例化,再将这个实例化好的对象放入beanWrapper中。之后再从这个beanWrapper中取出bean,和beanClass,再对这个bean应用MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition修改bean定义。其中主要的有CommonAnnotationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor。 CommonAnnotationBeanPostProcessor:这个类主要是为了支持一些常用的javax包下的一些注解,比如@PreDestroy,@Resource,@PostConstruct。会将所有带了**@PreDestroy的方法收集到destoryMethods中**,将**@PostConstruct的方法收集到initMethods中**。将**@Resource标记的字段注入和方法注入收集到injectedElements中**。之后会将这些信息存放到externallyManagedConfigMembers(注入信息),externallyManagedInitMethods,externallyManagedDestroyMethods中。AutowiredAnnotationBeanPostProcessor:这个类是为了处理@Autowired和@Value注解,和CommonAnnotationBeanPostProcessor差不多,之后会将这些信息存放到**externallyManagedConfigMembers(注入信息)**中。 如果需要将早期bean(实例化完成,没有进行其他任何操作的bean)放入第三级缓存中(singletonFactories),则放进去,这样可以用于解决循环依赖。填充bean: 为bean应用所有的InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法获取bean的resolvedAutowireMode,然后进行其他处理。(这个步骤好像又是在整些阴间的东西,可以不用管)为bean应用所有的InstantiationAwareBeanPostProcessor的postProcessProperties和postProcessPropertyValues。主要有CommonAnnotationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor。这2个会负责依赖注入。在注入时,会先获取到要注入的bean,此时就有可能会发送循环引用的问题。这个时候就可以再经过一堆漫长的步骤后将第5步中放入singletonFactories(第三级缓存)的对象取出来并注入,然后将在singletonFactories中移除这个对象,将这个对象添加到**earlySingletonObjects(第二级缓存)**中。经过这个步骤后,bean就完成了依赖注入了。 初始化Bean: invokeAwareMethods:处理BeanNameAware,BeanClassLoaderAware,BeanFactoryAware相关的注入方法。applyBeanPostProcessorsBeforeInitialization:为bean应用所有的BeanPostProcessor的postProcessBeforeInitialization。比如会执行各种各样的XXXAwarePostProcessor。主要有: CommonAnnotationBeanPostProcessor#postProcessBeforeInitialization:调用bean的initMethods(被@PostConstract标记的方法)。 invokeInitMethods:首先调用InitializingBean的afterPropertiesSet方法。再invokeCustomInitMethod(这个好像也是阴间的东西)。applyBeanPostProcessorsAfterInitialization:为bean应用所有的BeanPostProcessor的postProcessAfterInitialization。主要有: AnnotationAwareAspectJAutoProxyCreator#postProcessAfterInitialization,主要用于返回AOP代理对象。MethodValidationPostProcessor#postProcessAfterInitialization:和数据校验有关。@Validated,@Valid。 registerDisposableBeanIfNecessary:注册实现了DisposableBean接口的bean。 将此beanName移除出singletonsCurrentlyInCreation。bean就这样创建完成了。将实例化好的单例bean放入DefaultSingletonBeanRegistry的singletonObjects中。返回创建好的bean。

    12:finishRefresh

    清除上下文级别的资源缓存(例如来自扫描的ASM元数据)。初始化LifecycleProcessor。如果上下文中未定义,则使用DefaultLifecycleProcessor。调用LifecycleProcessor的onRefresh。会启动lifecycleBeans。发布一个ContextRefreshedEvent。LiveBeansView.registerApplicationContext(this);startWebServer 为tomcat的server的所有的service添加以前删除的connectors在启动时执行延迟加载检查connectors是否已启动把started标志设置为true 发布ServletWebServerInitializedEvent。

    13:resetCommonCaches

    重置Spring的通用反射元数据缓存
    Processed: 0.019, SQL: 9