Spring和springboot的整体流程

最近面试遇到了高频题目,spring和boot的启动和初始化的过程,这边简单总结下(理解大于死记硬背)

 

大体流程:(1)Spring装载bean过程(beanname,y依赖关系都是保存在了concurrentHashMap):
tomcat启动创建servlet,创建servletContext ,
ServletContext是一个web应用的上下文,是一个全局信息的存储空间,代表当前web应用
ServletContext创建之后,然后读取web.xml配置文件中的 <context-param></context-param>节点内容
servletContext调用 initWebApplicationContext 构建xmlwebapplicationContext
创建BeanFactory (DefaultListableBeanFactory)
通过ResourceLoader加载classpath下xml配置文件
通过XmlBeanDefinitionReader 中的loadBeanDefinition
解析文件为xml->document->Element
BeanDefinitionRegister 注册bean到IOC容器(concurrentHashMap)
 
WebApplicationContext : WebApplicationContext是专门为web应用准备的,他允许从相对于web根目录的路劲中装载配置文件完成初始化工作,从WebApplicationContext中可以获得ServletContext的引用,整个Web应用上下文对象将作为属性放置在ServletContext中,以便web应用可以访问spring上下文,spring中提供WebApplicationContextUtils的getWebApplicationContext(ServletContext src)方法来获得WebApplicationContext对象
WebApplicationContext扩展了ApplicationContext.在 WebApplicationContext中定义了一个常量 ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,在上下文启动时,
WebApplicationContext以此为键放置在ServletContext属性列表中,
 public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
}
 
将bean加载到factory的大致流程整理:
1)在某一时刻Spring调用了 Bean工厂 的 getBean(beanName) 方法。beanName可能是simpleController,或者simpleService,simpleDao,顺序没关系(因为后面会有依赖关系的处理)。我们假设simpleController吧。
2)getBean方法首先会调用Bean工厂中定义的getSingleton(beanName)方法,来判断是否存在该名字的bean单例,若果存在则返回,方法调用结束。
3)否则,Spring会检查是否存在父工厂,如果有则返回,方法调用结束。
4)否则,Spring 会检查该bean 定义(BeanDefinition实例,用来描述Bean结构,component-scan 扫描后,就是将beanDefinition实例放入Bean工厂,此时Bean还没有被实例化。)是否有依赖关系,如果有,执行1)步,获取依赖的bean实例。
5)否则,Spring会尝试创建这个bean实例,创建实例前,Spring会检查确定调用的构造器,并实例化该Bean。
6)实例化完成后,Spring会调用Bean工厂的populateBean方法来填充bean实例的属性,也就是我们前面提到的自动转配了。populateBean方法便是调用了BeanPostProcessor实例来完成属性元素的自动装配工作。
7)在元素装配过程中,Spring会检查被装配的属性是否存在自动装配的其他属性,然后递归调用getBean方法,直到所有@Autowired的元素都被装配完成。如在装配simpleController中的simpleService属性时,发现SimpleServiceImpl实例中存在@Autowired属性simpleDao,然后调用getBean(simpleDao)方法,同样会执行1)-7)整个过程。所以可以看成一个递归过程。
8)装配完成后,Bean工厂会将所有的bean实例都添加到工厂中来
通过bean工厂找bean ->判断bean是否是单例->父工厂找bean->找不到bean就创建该bean->创建先找有没有依赖父类有就实例化父类->调用构造器实例化bean->自动装配bean->发现依赖其他bean,重复上述步骤 ->直到所有被注解注入的bean被装配完,成功
先实例化。再装配
 
Springboot容器的初始化流程:
1.启动类的构造方法:初始化各种环境,获取spring.factory中的信息+注册各种监听
2,
执行run的时候:初始化环境,上下文,调用spring的reflesh注册bean,执行各种监听器
1.创建容器
2.准备容器(准备阶段):
一。设备context的enviroment(各种profile配置的属性)
二、如果存在开发主动设置的beanNameGenerator,resourceLoader就替换原有的这两个属性(spring获取bean的命名策略)
三、设置ContextInitializer :执行 在META-INF/spring.factories中以org.springframework.context.ApplicationContextInitializer为key配置一个或多个initialier 。
springboot中有两个initialier:
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\:
{
1.添加BeanFactoryPostProcessor---CachingMetadataReaderFactoryPostProcessor
-2.CachingMetadataReaderFactoryPostProcessor--在beanfactory注册自身RootBeanDefinition,并将其自身作为属性设置到internalConfigurationAnnotationProcessor中
}
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener:{
-1.添加ConditionEvaluationReportListener作为ApplicationListener
-2.主要是打印debugg日志
}
   四、注册ApplicationArguments和Banner以及启动类单例
   五、调用contextLoaded方法{
      -1.给ApplicationContextAware属于ApplicationContextAware设置applicationContext
      -2.将这些listener都添加到集合 然后统一发布容器准备成功事件,最终就是调用这些listener的onEvent方法
   六、SpringApplicationRunListener 目前只有EventPublishingRunListener,专门发布各种listener事件
3.刷新容器( spring的ioc容器开始初始化所有的非懒加载的单例bean ):
小知识:
自动注入不是指的@AutoWire 而是指的是beans的default-autowire="byType" 或在bean的autowire="byType" ,这样spring 回去ioc容器寻找类型相似的类型给其注入
1.调用beanFactoryPostProcessor 并实例化所有的bean
具体流程:
{
1.postProcessBeanFactory:可以在BeanFactory完成实例化后修改容器内部的BeanFactory。这时候所有的bean都被加载,但是没有bean被初始化。这就允许BeanFactoryPOSTProcessor重写或者添加配置,甚至可以提前初始化bean;
 
2.从beanFactory获取BeanDefinitionRegistryPostProcessor类型的beanDefinition,然后按照PriorityOrdered,Ordered,普通,进行实例化和调用postProcessBeanDefinitionRegistry;
 
    2.1BeanPostProcessor :接口定义了一个你可以自己实现的回调方法,来实现你自己的实例化逻辑、依赖解决逻辑等,如果你想要在         Spring完成对象实例化、配置、初始化之后实现自己的业务逻辑,你可以补充实现一个或多个BeanPostProcessor的实现:
    {
   类的构造方法->类的get,set方法->BeanPostProcessor .postProcessBeforeInitialization()(类真正初始化之前调用)->加载类的属       性->BeanPostProcessor .postProcessAfterInitialization方法
    }
}
4 注册钩子
-1.卸载容器
-2.发布卸载事件
-3.lifecycleProcessor的onclose方法
-4.摧毁bean,关闭beanfactory,关闭一些子容器
 
 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值