前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring-IoC容器工作原理

Spring-IoC容器工作原理

作者头像
茶半香初
发布2021-11-26 14:25:43
2680
发布2021-11-26 14:25:43
举报
文章被收录于专栏:程序员那点事

IoC容器工作原理

在这里插入图片描述
在这里插入图片描述

1. 创建beanFactory

容器底层用DefaultListableBeanFactory,即实现了BeanDe finitionRegistry,又实现了BeanFactory java配置 :

代码语言:javascript
复制
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);      

this() 方 法 ----> 调父类无参构造器

代码语言:javascript
复制
public GenericApplicationContext(){ 
  this.beanFactory = new DefaultListableBeanFactory(); 
}

在 容 器 启 动 之 前 就 创 建 beanFactory xml 配 置 :

代码语言:javascript
复制
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("Spring.xml"); 

调 refresh() 后 ,即容器启动过程中创建 beanFactory

代码语言:javascript
复制
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 
> refreshBeanFactory(); // AbstractApplicationContext#refreshBeanFactory 

先创建DefaultListableBeanFactory实例,然后解析xml配置文件,注册bean到beanFactory ,最后再将beanFactory赋值给容器

代码语言:javascript
复制
DefaultListableBeanFactory beanFactory = createBeanFactory(); 
beanFactory.setSerializationId(getId()); 
// 定制beanFactory,设置参数 
customizeBeanFactory(beanFactory); 
// 注册spring的xml配置的bean到beanFactory,此时容器还未指定beanbeanFactory
loadBeanDefinitions(beanFactory); 
// 给容器指定beanFactory 
synchronized(this.beanFactoryMonitor){ 
  this.beanFactory = beanFactory; 
} 

2. 注册bean

核心原理 : 通过调用registerBeanDefinition方法将bean的beanName----beanDe finition注册到beanFactory

代码语言:javascript
复制
DefaultListableBeanFactory#registerBeanDefinition   //实现了BeanDefinitionRegistry 
> beanDefinitionMap.put(beanName,beanDefinition); //缓存beanDefinition 

代码示例 :

代码语言:javascript
复制
// 拿到工厂 实现了BeanDefinitionRegistry 
DefaultListableBeanFactorybeanFactory = context.getDefaultListableBeanFactory(); 
// 创建一个beanDefinition 
RootBeanDefinitionbeanDefinition = newRootBeanDefinition(User.class); 
// 注册 
beanFactory.registerBeanDefinition("user",beanDefinition); 

java配置 : 容器启动过程中,会调用ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry解析注解,注册bean

代码语言:javascript
复制
invokeBeanFactoryPostProcessors(beanFactory); // 解析注解,注册bean 
> ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry 

ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry中有两个很重要的方法

代码语言:javascript
复制
// 解析配置类@ComponentScan(bean注册到容器)@Import @ImportResource @Bean 
parser.parse(candidates); 
// 注册bean到容器 
// 注册实现了ImportSelector的bean 
// 方法bean注册到容器 
// @ImportResource("spring.xml")配置的bean注册到容器 
// 实现ImportBeanDefinitionRegistrar的bean注册到容器 
this.reader.loadBeanDefinitions(configClasses); 

解析注解

代码语言:javascript
复制
parser.parse(candidates); 
> ConfigurationClassParser#processConfigurationClass 
> ConfigurationClassParser#doProcessConfigurationClass 

ConfigurationClassParser#doProcessConfigurationClass会处理@ComponentScan,@Import,@ImportResource,@Bean @ComponentScan会将@Component修饰的bean注入到容器

代码语言:javascript
复制
ClassPathBeanDefinitionScanner#doScan 
> 
// 找到@Component修饰的类的beanDefiniton集合 
Set<BeanDefinition> candidates = findCandidateComponents(basePackage); 
// 注册bean 
registerBeanDefinition(definitionHolder,this.registry); 

注册bean

代码语言:javascript
复制
this.reader.loadBeanDefinitions(configClasses)
> ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass 
if(configClass.isImported()){ 
  // implementsImportSelector的bean注册 
  registerBeanDefinitionForImportedConfigurationClass(configClass); 
} 
for(BeanMethodbeanMethod : configClass.getBeanMethods()){ 
  // 方法bean注册到容器 
  loadBeanDefinitionsForBeanMethod(beanMethod); 
} 
// @ImportResource("spring.xml")配置的bean注册到容器loadBeanDefinitionsFromImportedResources(configClass.getImportedResources()); 
//实现ImportBeanDefinitionRegistrar的bean注册到容器 
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars()); 

xml配置:

代码语言:javascript
复制
ConfigurableListableBeanFactorybeanFactory = obtainFreshBeanFactory(); 
> refreshBeanFactory(); // AbstractApplicationContext#refreshBeanFactory 

将beanFactory赋值给容器之前解析xml,并且注册bean

代码语言:javascript
复制
DefaultListableBeanFactorybeanFactory = createBeanFactory(); 
beanFactory.setSerializationId(getId()); 
// 定制beanFactory,设置参数 
customizeBeanFactory(beanFactory); 
// 注册spring的xml配置的bean到beanFactory,此时容器还未指定beanbeanFactoryloadBeanDefinitions(beanFactory); 
// 给容器指定beanFactory 
synchronized(this.beanFactoryMonitor){ 
  this.beanFactory = beanFactory ; 
} 

解析xml loadBeanDefinitions(beanFactory)最终会调DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions

代码语言:javascript
复制
// 注册spring的xml配置的bean到beanFactory,此时容器还未指定beanbeanFactory
loadBeanDefinitions(beanFactory); 
> DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions 
preProcessXml(root); 
parseBeanDefinitions(root,this.delegate); // 解析xml 
postProcessXml(root); 
> DefaultBeanDefinitionDocumentReader#parseDefaultElement 
else if(delegate.nodeNameEquals(ele,BEAN_ELEMENT)){ 
// 解析bean 
processBeanDefinition(ele,delegate); 
} 
> DefaultBeanDefinitionDocumentReader#processBeanDefinition 
// 注册最后修饰后的实例beanDefinition 
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder,
getReaderContext().getRegistry()); 

注册bean BeanDefinitionReaderUtils#registerBeanDefinition中会注册bean

代码语言:javascript
复制
// 注册beanDefiniton 
registry.registerBeanDefinition(beanName,definitionHolder.getBeanDefinition()); 

3. 创建bean实例

容器启动过程中会实例化非懒加载单例bean,通过AbstractBeanFactory创建bean的实例

代码语言:javascript
复制
AbstractApplicationContext#refresh 
// Instantiateallremaining(non-lazy-init)singletons. 
// 实例化所有剩余的(非懒加载)单例 。 
> finishBeanFactoryInitialization(beanFactory); 
> AbstractApplicationContext#getBean(String)

调用context.getBean(name)获取bean实例,实际会去调用AbstractBeanFactory的getBean()方法 。

代码语言:javascript
复制
AbstractApplicationContext #getBean(String)
> AbstractBeanFactory #getBean(String)

调用AbstractBeanFactory#doGetBean,先从singletonObjects中去获取bean

代码语言:javascript
复制
// 转换对应的beanName 
// 1. 带 & 前缀的去掉前缀 
// 2. 从aliasMap中找name对应id,bean没有配id就用name 
finalStringbeanName = transformedBeanName(name);
// 先从缓存singletonObjects中找,没有则去创建 
// 处理循环依赖的问题,比如A ->B,B->A 
ObjectsharedInstance = getSingleton(beanName); 
// 判断单例 
if(mbd.isSingleton()){ 
	sharedInstance = getSingleton(beanName,()-> { 
		return createBean(beanName,mbd,args); 
  });   
  bean = getObjectForBeanInstance(sharedInstance,name,beanName,mbd); }  

调用AbstractAutowireCapableBeanFactory#doCreateBean返回bean

代码语言:javascript
复制
AbstractAutowireCapableBeanFactory#createBean(String,RootBeanDefinition,Object[])
// 返回bean实例 
> Object beanInstance = doCreateBean(beanName,mbdToUse,args); 

实例化bean 调用AbstractAutowireCapableBeanFactory#doCreateBean

代码语言:javascript
复制
/** 
* 第2次调用后置处理器 
* 创建bean实例,并将实例放在包装类BeanWrapper中返回 
* 1. 通过工厂方法创建bean实例 
* 2. 通过构造方法自动注入创建bean实例 
* 3. 通过无参构造器创建bean实例 
*/ 
instanceWrapper = createBeanInstance(beanName,mbd,args); 
finalObjectbean = instanceWrapper.getWrappedInstance(); 

填充bean

代码语言:javascript
复制
// 填充bean设置属性 
InstantiationAwareBeanPostProcessors 
// 第5次,第6次调用后置处理器   注入依赖 
populateBean(beanName,mbd,instanceWrapper); 

初始化bean

代码语言:javascript
复制
// 初始化bean 
exposedObject = initializeBean(beanName,exposedObject,mbd); 

返回bean

代码语言:javascript
复制
// 返回类型判断FactoryBeanBeanFactroy 
bean = getObjectForBeanInstance(sharedInstance,name,beanName,mbd);> 
//涉及FactoryBean的判断,直接返回普通bean的条件类型是否是FactoryBean || name首字符是否是 & 
if(!(beanInstanceinstanceofFactoryBean)|| BeanFactoryUtils.isFactoryDereference(name){ 
	return beanInstance ; 
} 
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/12/27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • IoC容器工作原理
    • 1. 创建beanFactory
      • 2. 注册bean
        • 3. 创建bean实例
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档