
SpringBoot启动过程深度解析——Bean的创建过程以及扩展点
发布日期:2023-09-20 01:37:28
浏览次数:1
分类:技术文章
本文共 14026 字,大约阅读时间需要 46 分钟。
SpringBoot启动过程深度解析——Bean的创建过程以及扩展点
Bean生命周期的扩展点:
1.重写Bean类中的方法: 【为什么要提供此扩展点?当单例Bean引用了多例Bean时,返回的是单例Bean,这是一个BUG。需要提前进行CGlib代理,后续通过getBean获取多例属性Bean】 【为了解决类似问题的有:configurationClassPostProcessor 也是为了解决 @Bean是多例的情况,而提前进行代理,后续通过GetBean获取生成多例Bean 【enhanceConfigurationClasses方法】】 lookup-method、replace-method 2.Bean实例化的方式有以下几种: 【直接返回Bean,不经过初始化的详细流程】 实现factoryBean 【直接对象】 【相当于重写了createBean方法,替代createBean方法直接返回对象】 【直接返回Bean,不经过初始化的详细流程】 实现InstantiationAwareBeanPostProcessor 【直接对象】 【在createBean方法中调用,在doCreateBean之前调用,直接返回对象】 【需要经历初始化的详细流程】 向BeanDefinition设置自定义supplier 【只是实例化,创建BeanWrapper封装在里面】【创建一个BeanFactoryPostProcessor,设置对应BeanDefinition的setSupplier,后续在doCreateBean方法调用createBeanInstance】 【需要经历初始化的详细流程】 实现factoryMethod 【只是实例化,创建BeanWrapper封装在里面】【在配置类中@Bean注解的方法如果是static修饰的,那么这种bean的实例化就是通过FactoryMethod实现的。】 【需要经历初始化的详细流程】 正常spring创建流程 【通过反射实例化原对象和代理对象】3.BeanPostProcessor【普通的处理器接口】 接口方法1:postProcessBeforeInitialization(在Bean实例化之前调用) 接口方法2:postProcessAfterInitialization(在Bean实例化之后调用) 此接口的子类接口: 1.DestructionAwareBeanPostProcessor 【销毁Bean前调用】 1.postProcessBeforeDestruction方法:在调用Bean的Destroy方法前调用 2.InstantiationAwareBeanPostProcessor 【spring用于抑制某些Bean的创建: 代理、延迟初始化、字段注入、注解增强... 如果自己要实现这种类型,请实现这个 InstantiationAwareBeanPostProcessorAdapter】 1.【实例化后】resolveAfterInstantiation方法 2.【实例化前】resolveBeforeInstantiation方法:还没doCreateBean的时候调用:AbstractAutowireCapableBeanFactory.createBean() 【此处 先执行before方法 如果通过此方法返回了Bean,则直接执行after的方法】 3.【初始化前】postProcessBeforeInitialization方法 4.【初始化后 一般用于设置属性】postProcessAfterInitialization方法 5.【属性值处理】postProcessProperties方法:在populateBean方法时,先执行 6.【属性值处理】postProcessPropertyValues方法:在populateBean方法时,如果postProcessProperties 放回null ,则会执行 3.MergedBeanDefinitionPostProcessor 【用于合并父类的BeanDefinition信息 】 1.postProcessMergedBeanDefinition方法 :doCreateBean的时候调用(instanceWrapper之后,populateBean之前) 2.resetBeanDefinition方法 4.SmartInstantiationAwareBeanPostProcessor【继承MergedBeanDefinitionPostProcessor】 1.【预测某些Bean的类型】predictBeanType方法 2.【创建Bean时,自定义返回对应的构造器】determineCandidateConstructors方法:在createBeanInstance方法获取构造器时,就会调用此方法返回特殊的构造方法 3.【解决循环依赖问题,创建代理对象Bean】getEarlyBeanReference方法 【提前暴露代理生成方法,三级缓存】createBean方法 -> 实例化之后,初始化之前调用 -> addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); 【当三级缓存的方法被调用时才会调用当前接口方法】() -> getEarlyBeanReference(beanName, mbd, bean) 【最终的调用地方:】遍历所有的SmartInstantiationAwareBeanPostProcessor方法getEarlyBeanReference 5.InitDestroyAnnotationBeanPostProcessor 【主要处理@PreDestroy 和 @PostConstruct】4.@PostConstruct 被声明的方法将在执行完BeanPostProcessor的postProcessBeforeInitialization方法之后,马上执行该方法5.InitializingBean【实例化Bean回调接口】 接口方法:afterPropertiesSet(在Bean设置完属性值之后调用) 6.@Bean(initMethod="xxxMethodName") 被声明的方法将在执行完InitializingBean的afterPropertiesSet方法之后,马上执行该方法7.@PreDestroy 被声明的方法将在正常销毁Bean时,调用执行 8.@Bean(destroyMethod="xxxMethodName") 被声明的方法将在正常销毁Bean时,调用执行
Bean创建过程逻辑图
Bean创建过程文字描述逻辑
spring启动创建Bean标准入口: refresh() # finishBeanFactoryInitialization()preInstantiateSingletons()方法主要逻辑: 1.准备类型转换器 DefaultConversionService 2.内置的值的处理器 StringValueResolver 3.加载时织入增强器 LoadTimeWeaverAware 4.禁止使用临时类加载器进行类型匹配 5.冻结所有的bean定义,说明注册的bean定义将不被修改或任何进一步的处理 6.调用preInstantiateSingletons(); 实例化剩下的单例对象 【Bean创建入口】preInstantiateSingletons(); 实例化剩下的单例对象方法逻辑: 遍历集合的对象【所有非延迟非抽象单例bean】 1.合并父类BeanDefinition 2.【创建FactoryBean】 2.1 通过"&"+BeanName创建 2.2 判断是否饥饿加载Bean,通过调用getBean(BeanName) 注册工厂Bean生成的Bean实例 3.【创建普通Bean开始】 -> 【getBean方法开始调用】 -> 【doGetBean方法开始调用】 3.1 转换beanName (1.去除&符号 2.从aliasMap得到最终的BeanName) 3.2 判断是否已经存在一、二、三级缓存对象 -> 获取FactoryBean接口的对象 3.3 不存在缓存对象 -> 检查当前单例对象是否在创建过程中 -> 【先获取当前容器的BeanDefinition,如果没有就直接通过父容器 getBean】 -> 标记正在创建 -> 合并父类BeanDefinition -> 检查mbd的合法性\抽象类抛异常 -> 【处理@DependOn,优先实例化依赖的bean】 -> 【递归优先实例化被依赖的Bean】 -> 【单例Bean创建】 -> 【getSingleton方法开始调用】 -> 一级缓存加锁 -> 判断不存在一级缓存,没有销毁中 -> 加入创建中集合 -> 【调用createBean / 调用FactoryBean的方法】 -> 通过BeanName解析成Class对象 -> 【标记重写方法,不限于lookup-method、replace-method】 -> 【直接返回Bean对象,结束.调用InstantiationAwareBeanPostProcessor】 -> 【先调用 applyBeanPostProcessorsBeforeInstantiation】 ->【AOP 代理的生成 :实现类:AbstractAutoProxyCreator】 -> 【得到bean不为空,调用 applyBeanPostProcessorsAfterInitialization】 -> 【doCreateBean方法的调用】 -> 【创建BeanWrapper】 ->【如果有InstanceSupplier,执行返回】 ->【如果有FactoryMethod,执行返回】 ->【bean构造器解析缓存就使用,执行返回】 -> 如果是autowire 使用ConstructorResolver.autowireConstructor最终调用 instantiationStrategy.instantiate -> 非autowire 使用默认的 instantiationStrategy.instantiate ->【通过BeanPostProcessor获取的构造器】 -> (主要是匹配@Autowire注释的构造器)【调用SmartInstantiationAwareBeanPostProcessor接口的determineCandidateConstructors方法返回构造器】 ->【如果是autowire的构造器,执行返回,ConstructorResolver.autowireConstructor】 ->【处理@Primary的构造器,执行返回,ConstructorResolver.autowireConstructor】 ->【使用默认无参的构造器实例化对象,执行返回,SimpleInstantiationStrategy.instantiate】 ->【beanPostProcessor去修改合并的beanDefinition】 -> 【MergedBeanDefinitionPostProcessor接口实现类执行postProcessMergedBeanDefinition方法】(主要处理@ -> 实现类:CommonAnnotationBeanPostProcessor 实现了 InitDestroyAnnotationBeanPostProcessor 1.【不是调用】主要是获取 @PostConstruct 注释的方法,并排序【@PostConstruct 父类优先执行】 -> 这个注解是JDK的 2.【不是调用】主要是获取 @PreDestroy 注释的方法,并排序【@PreDestroy 子类优先执行】 -> 这个注解是JDK的 3. 向BeanDefinition设置 ExternallyManagedInitMethod = init 、 ExternallyManagedDestroyMethod 4.【获取@Resource @WebServiceRef @EJB 父类优先注册的信息属性和方法 】 5. 向BeanDefinition设置 ExternallyManagedConfigMember = xxx -> 实现类:AutowireAnnotationBeanPostProcessor 4.【获取@Autowire @Value @Inject 父类优先注册的信息】 5. 向BeanDefinition设置 ExternallyManagedConfigMember = xxx ->【三级缓存,判断当前bean是否需要提前曝光:单例&允许循环依赖&当前bean正在创建中,检测循环依赖】 ->【三级缓存添加,提前暴露代理/创建Bean的方法】 【三级缓存存放的是 getEarlyBeanReference方法,其中被其他Bean引用而被调用创建时,getSingleton方法,来调用该匿名方法来返回代理/原对象】 (【AOP处理】在getEarlyBeanReference方法中,会执行SmartInstantiationAwareBeanPostProcessor的方法getEarlyBeanReference) ->【populateBean 对bean的属性进行填充】 ->【一般用于设置属性 可直接return; 如果有此实现类:InstantiationAwareBeanPostProcessor,会执行接口方法postProcessAfterInstantiation】【这里如果返回FALSE,直接返回】 -> 声明和获取mbd中的PropertyValues ->【处理XML的 autowire的属性值,1.byName 2.byType】 -> byName【可以处理集合指定的特定类型】 -> byType【可以处理集合指定的特定类型】 ->【处理注解值 执行InstantiationAwareBeanPostProcessor接口方法:postProcessProperties】 ->【AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor会执行】 ->【@Autowire、@Value、@Resource、@Inject、@WebServiceRef、@EJB 会在此注入,和创建对应的属性Bean】 ->【执行InstantiationAwareBeanPostProcessor接口方法:postProcessPropertyValues】 ->【依赖检查】 ->【根据property的标签的属性值,完成各种属性值的解析和赋值工作 applyPropertyValues方法】 ->【此处如果循环依赖,开始加载创建中的Bean】 ->【调用getSingleton方法获取】 ->【AOP等处理,从三级缓存中执行getEarlyBeanReference方法,返回早期对象】 ->【移除三级缓存,存放二级缓存!!!!】 ->【initializeBean 执行初始化逻辑】 ->【Aware接口处理器,调用BeanNameAware、BeanClassLoaderAware、beanFactoryAware】 ->【BeanPostProcessor接口的postProcessBeforeInitialization执行】 ->【ApplicationContextAwareProcessor】【设置EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware】 ->【ConfigurationClassPostProcessor#ImportAwareBeanPostProcessor】【处理ImportAware接口中,注解信息的修改】 ->【CommonAnnotationPostProcessor】【调用@PostConstruct的方法,也就是init方法】 -> ... ... ->【调用初始化方法】 ->【InitializingBean接口的方法afterPropertiesSet】 ->【在bean上调用指定的自定义init方法,从mbd.getInitMethodName()来执行,也就是@Init方法,@Pre】 ->【BeanPostProcessor接口的postProcessAfterInitialization执行】 ->【ApplicationListenerDetector】【如果是ApplicationListener接口实现的话,需要注册到多播器中】 ->【循环依赖的检测,如果还有依赖的Bean还没创建,就会抛异常】 【只有二级缓存时,会在此报异常, A有代理B,代理B没有A,原B有A】 ->【可以在此注册Bean工作,1.实现了DisposableBean接口,2.自定义destroy-method,3.DestructionAwareBeanPostProcessor处理销毁】 ->【如果是单例,可以注册销毁一些销毁方法】 ->【如果是其他作用域的Bean,则注册一个销毁的回调方法】 ->【Bean创建结束】 ->【Bean创建结束】 ->【将单例标记为不在创建中】 ->【一级缓存存放,移除三级缓存,移除二级缓存,BeanName注册到单例集合中】 ->【Bean创建结束】 ->【如果是FactoryBean会直接返回getObject方法实例】 ->【如果是原型模式的创建】 ->【标记创建中】 ->【createBean】 ->【取消创建中】 ->【如果是FactoryBean会直接返回getObject方法实例】 ->【如果是其他作用域的Bean的创建】 ->【标记创建中】 ->【createBean】 ->【取消创建中】 ->【如果是FactoryBean会直接返回getObject方法实例】 ->【检查requiredType是否与实际Bean实例的类型匹配】 ->【获取TypeConverter进行转换】 ->【Bean创建结束】 ->【Bean创建结束】 遍历beanNames,触发所有SmartInitializingSingleton的后初始化回调 1.【触发所有SmartInitializingSingleton的Bean的afterSingletonsInstantiated方法】
转载地址:https://blog.csdn.net/weixin_39072857/article/details/130112179 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
哈哈,博客排版真的漂亮呢~
[***.90.31.176]2023年09月13日 19时24分42秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
电商财务结算系统重构实践
2019-03-07
跨进程调用实现之消息组件RabbitMq实例
2019-03-07
小谈mysql存储引擎优化
2019-03-07
java疫苗之殇?关于java类加载器的一些思考
2019-03-07
Java正则表达式简单介绍
2019-03-07
数据库连接池原理
2019-03-07
预防缓存穿透方案设计
2019-03-07
浅谈软件工程中的代码评审
2019-03-07
Vue前端测试实践
2019-03-07
财务系统库存重构现有量方案追忆
2019-03-07
一致性算法Raft的原理简介与源码初探
2019-03-07
关于mysql事务&MVCC以及锁机制的总结
2019-03-07
equals和==
2019-03-07
JVM、JRE、JDK、Java SE、Java EE、Java ME
2019-03-07
索引(Index)
2019-03-07
向下兼容、向上兼容、向前兼容、向后兼容
2019-03-07
每天记录学习的新知识 : 导入信任证书到 Jdk
2019-03-07
每天记录学习的新知识 : gradle配置国内镜像
2019-03-07
每天记录学习的新知识 : 编译成功但是无法运行
2019-03-07
每天记录学习的新知识 : 绑定完GitHub怎么提交项目
2019-03-07