Spring ioC源码深入剖析Bean的实例化 2

简介: Spring ioC源码深入剖析Bean的实例化

4.3 容器13大模板方法之三:prepareBeanFactory(beanFactory)

【准备bean工厂】

//3、【准备bean工厂】为BeanFactory配置容器特性,例如类加载器、表达式解析器、注册默认环
境、后置管理器
prepareBeanFactory(beanFactory);
/1、设置 BeanFactory 的类加载器
//2、设置 BeanFactory 的表达式解析器
//3、设置 BeanFactory 的属性编辑器
//4、智能注册

tips

当前代码逻辑简单、且非核心

4.4 容器13大模板方法之四:postProcessBeanFactory(beanFactory)

【后置处理器Bean工厂】空方法

// 4、【后置处理器Bean工厂】此处为空方法,子类的实现
postProcessBeanFactory(beanFactory);

需要注意:

BeanFactoryPostProcessor和BeanPostProcessor,此处是前者

BeanFactoryPostProcessor 是容器级别的后处理器,对其他容器中的bean 没有影响


tips:子类实现skip当前方法


4.5 容器13大模板方法之五:invokeBeanFactoryPostProcessors()

【调用bean工厂后置处理器】

//调用顺序一:bean定义注册后置处理器
//调用顺序二:bean工厂后置处理器
//重点
//执行bean定义注册后置处理器!!!!!!!!!!!!
//执行BeanF工厂后置处理器!!!!!!!!!!!!!!!!!!!!!!!!!!!
public static void invokeBeanFactoryPostProcessors()

讲解重点(断点跟踪、类继承关系、架构图讲解)

关于invokeBeanFactoryPostProcessors为什么为true?

if (beanFactory instanceof BeanDefinitionRegistry) {
...略
}

找到核心逻辑

//164行
// 执行bean定义注册后置处理器!!!!!!!!!!!!
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
//222行
//执行BeanF工厂后置处理器!!!!!!!!!!!!!!!!!!!!!!!!!!!
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

找到我们项目中的自定义两个处理器

进行断点追踪执行过程

com.spring.test.config.BeanDefinitionRegistryPostProcessorTest
com.spring.test.config.BeanFactoryPostProcessorTest
此次代码略..........

tips

invoke方法近200行,只看核心

4.6 容器13大模板方法之六:registerBeanPostProcessors(beanFactory)

【注册bean后置处理器】

//6、【注册bean后置处理器】只是注册,但是不会反射调用
//功能:找出所有实现BeanPostProcessor接口的类,分类、排序、注册
registerBeanPostProcessors(beanFactory);

讲解重点(断点跟踪、类继承关系、架构图讲解)

//调用顺序一:bean定义注册后置处理器
//调用顺序二:bean工厂后置处理器
// 核心:查看重要的3步;最终目的都是实现bean后置处理器的注册
// 第一步: implement PriorityOrdered
// 第二步: implement Ordered.
// 第三步: Register all internal BeanPostProcessors.

4.7 容器13大模板方法之七:initMessageSource()

【初始化消息源】国际化问题i18n

//7、【初始化消息源】国际化问题i18n,参照https://nacos.io/
initMessageSource();
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
//将这个messageSource实例注册到Bean工厂中
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME,
this.messageSource);

关于beanFactory.registerSingleton( org.springframework.beans.factory.support.DefaultListableBeanFactory#registerSingleton将新建的这个bean手动注册到bean工厂步骤如下


调用:

org.springframework.beans.factory.support.DefaultListableBeanFactory#manualSingletonNames

这个集合器set中然后:先去一级缓存去找,没有,直接放到一级缓存。移除二级三级缓存


最后:设置bean公厂、放到集合

4.8 容器13大模板方法之八:initApplicationEventMulticaster()

【初始化应用程序事件多路广播】

//8、【初始化应用程序事件多路广播】初始化自定义的事件监听多路广播器,(观察
者)S
initApplicationEventMulticaster();

tips:

需要理解观察者设计模式

重点:演示多播和容器发布

/**
* 如果没有,则默认采用SimpleApplicationEventMulticaster行事件的广播
*/
this.applicationEventMulticaster = new
SimpleApplicationEventMulticaster(beanFactory);
//将多播注册到Bean工厂
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME,
this.applicationEventMulticaster);

关于beanFactory.registerSingleton( org.springframework.beans.factory.support.DefaultListableBeanFactory#registerSingleton

将新建的这个bean手动注册到bean工厂

步骤如下

调用:

org.springframework.beans.factory.support.DefaultListableBeanFactory#manualSingletonNames

这个集合器set中

然后:先去一级缓存去找,没有,直接放到一级缓存。移除二级三级缓存

最后:设置bean公厂、放到集合

4.9 容器13大模板方法之九:onRefresh()

【刷新】 子实现:默认情况下不执行任何操作

// 9、【刷新】具体的子类可以在这里初始化一些特殊的 Bean(在初始化singleton beans 之前)
onRefresh();

4.10 容器13大模板方法之十:registerListeners()

【注册所有监听器】

//10、【注册所有监听器】,监听器需要实现 ApplicationListener 接口。
registerListeners();

讲解重点(断点跟踪、类继承关系、架构图讲解)

//获取所有实现了ApplicationListener,然后进行注册
//查找顺序
//1、集合applicationListeners查找
//2、bean工厂找到实现ApplicationListener接口的bean
//3、this.earlyApplicationEvents;准备刷新(启动第一步设置)

4.11 容器13大模板方法十一:finishBeanFactoryInitialization(beanFactory)

核心:【完成bean工厂初始化操作】

//11、 【完成bean工厂初始化操作】负责初始化所有的 singleton beans,反射生
成对象/填充
//此处开始调用Bean的前置处理器和后置处理器
finishBeanFactoryInitialization(beanFactory);

讲解重点(断点跟踪、类继承关系、架构图讲解)

//1、设置辅助器:例如:解析器、转换器、类装载器
//2、实例化(反射)
//3、填充
//4、调用前置、后置处理器
//1、先从一级缓存拿(or 正在创建中),如果正在创建有,最后return null,说明此处为实例化
//2、在从二级缓存拿
//3、在从三级缓存拿
//以上三步为解决循环依赖
//4、getBean调用的时候,直接从一级缓存取出
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference)
{
//先从一级缓存中拿,此处为空
Object singletonObject = this.singletonObjects.get(beanName);
// 下面isSingletonCurrentlyInCreation的如果有值,即为true,说明当前线程是实例化
中...
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName))
{
synchronized (this.singletonObjects) {
//在从二级缓存拿
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//在从三级缓存拿
ObjectFactory<?> singletonFactory =
this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName,
singletonObject);
this.singletonFactories.remove(beanName);
    }
   }
  }
 }
return singletonObject;
}

上面的代码总结:

先从一级缓存拿(此处如果为空,正在创建,直接return)为空,在从二级缓存拿还为空;在从三级缓存拿将三级缓存内容赋值给二级缓存

重点关注4个方法(重要)

调用时机:实例化(反射)对象/填充/回调后置(循环依赖&三级缓存)

调用入口:

xx.getBean()

容器初始化

getBean
doGetBean
createBean
doCreateBean

实例化核心

org.springframework.beans.BeanUtils#instantiateClass(java.lang.reflect.Construct
or<T>, java.lang.Object...)

注入核心

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#pop
ulateBean

调用bean的前置、后置方法(这个时候bean已经实例化、注入完毕了)\

//注意:
//1、先调用bean的前置处理器
//中间过程:调用bean的init方法或者实现了 InitializingBean 接口,调用
afterPropertiesSet() 方法
//2、后调用bean的后置处理器

最后一次机会的回调(实例化后注入前)

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#pop
ulateBean
================================================================================
===
 boolean continueWithPropertyPopulation = true;
//如果存在这实现这个接口的bean
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp =
(InstantiationAwareBeanPostProcessor) bp;
// postProcessAfterInstantiation如果返回 false,代表不需要进行后
续的属性设值
if
(!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
   }
  }
 }
}

4.12 容器13大模板方法十二:finishRefresh()

【完成刷新】

protected void finishRefresh() {
// 1、清除上下文级资源缓存
clearResourceCaches();
// 2、LifecycleProcessor接口初始化
// ps:当ApplicationContext启动或停止时,它会通过LifecycleProcessor来与所有声明
的bean的周期做状态更新
// 而在LifecycleProcessor的使用前首先需要初始化
initLifecycleProcessor();
// 3、启动所有实现了LifecycleProcessor接口的bean
//DefaultLifecycleProcessor,默认实现
getLifecycleProcessor().onRefresh();
// 4、发布上下文刷新完毕事件到相应的监听器
//ps:当完成容器初始化的时候,
// 要通过Spring中的事件发布机制来发出ContextRefreshedEvent事件,以保证对应的监听
器可以做进一步的逻辑处理
publishEvent(new ContextRefreshedEvent(this));
// 5、把当前容器注册到到MBeanServer,用于jmx使用
LiveBeansView.registerApplicationContext(this);
}

tips:

不重要

4.13 容器13大模板方法十三:resetCommonCaches()

【重设公共缓存】

//15、重设公共缓存
resetCommonCaches();
//清除内核缓存;因为我们的对象已经实例化并且注入完毕了
//中间过程数据(缓存)就不在需要了
protected void resetCommonCaches() {
    //清除之前声明过的方法和列的缓存
ReflectionUtils.clearCache();
//清除解析类型的缓存、序列化缓存
ResolvableType.clearCache();
//清除所有的类加载器
CachedIntrospectionResults.clearClassLoader(getClassLoader());
}


目录
相关文章
|
24天前
|
XML 安全 Java
|
1天前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
|
1天前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
|
6天前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
35 6
|
8天前
|
XML Java 数据格式
🌱 深入Spring的心脏:Bean配置的艺术与实践 🌟
本文深入探讨了Spring框架中Bean配置的奥秘,从基本概念到XML配置文件的使用,再到静态工厂方式实例化Bean的详细步骤,通过实际代码示例帮助读者更好地理解和应用Spring的Bean配置。希望对你的Spring开发之旅有所助益。
53 3
|
22天前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
41 2
|
22天前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
32 1
|
4月前
|
XML Java 数据格式
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
这篇文章是Spring5框架的实战教程,主要介绍了如何在Spring的IOC容器中通过XML配置方式使用外部属性文件来管理Bean,特别是数据库连接池的配置。文章详细讲解了创建属性文件、引入属性文件到Spring配置、以及如何使用属性占位符来引用属性文件中的值。
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
|
6月前
|
XML Java 数据格式
Spring5系列学习文章分享---第一篇(概述+特点+IOC原理+IOC并操作之bean的XML管理操作)
Spring5系列学习文章分享---第一篇(概述+特点+IOC原理+IOC并操作之bean的XML管理操作)
51 1
|
3月前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
264 18