Bean从扫描到创建

5 篇文章 0 订阅

spring容器的启动
以ClassPathXmlApplicationContext启动spring容器为例:
首先,ClassPathXmlApplicationContext(“applicationContext.xml”) 通过父类把”applicationContext.xml”文件设置到configLocations参数上;
其次,ClassPathXmlApplicationContext继承自 AbstractXmlApplicationContext,而AbstractXmlApplicationContext继承自AbstractRefreshableConfigApplicationContext;AbstractRefreshableConfigApplicationContext实现了InitializingBean,
所以spring启动会调用

public void afterPropertiesSet() {
    if (!this.isActive()) {
        this.refresh();
    }
}

refresh()方法是钩子方法,会调用到子类AbstractApplicationContext.refresh()方法中,
而该方法的逻辑包含以下几方面

一、 obtainFreshBeanFactory()
作用:xml解析和注册beanDefinition对象
1、加载xml文件
2、解析出xml文件中标签,根据标签的头信息得到标签的namespace url
3、根据component标签的namespace url 从META-INF的spring.handlers文件中找到对应的handler接口类
4、调用handler的接口类里的init()方法,init方法是注册了各种自定义标签的解析类
5、根据namespaceUri找到对应的解析类,然后调用paser方法完成标签解析
6、parser方法,将扫描到的对象封装为beanDefinition对象,注册到beanDefinitionNams和beanDefinitionMaps容器中。

二、 invokeBeanFactoryPostProcessors()
该方法主要是完成对(
BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor
) 这两个接口的调用

知识点1:beanDefinitionRegisterPostProcessor 继承 beanFactoryPostProcessor

  1. 继承了beanDefinitionRegisterPostProcessor的类会在spring启动的时候,优先实例化。
//获取实现了BeanDefinitionRegistryPostProcessor接口的
所有类的BeanDefinition对象的beanName并实例化.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

for (String ppName : postProcessorNames) {
		//判断是否实现了排序接口 PriorityOrdered
	if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
		currentRegistryProcessors.add(
		beanFactory.getBean(ppName,BeanDefinitionRegistryPostProcessor.class)
		);
		processedBeans.add(ppName);
				}
	}
  1. beanDefinitionRegisterPostProcessor的一个重要应用是ConfigurationClassPostProcessor类,
    该类是对@bean @Configuration @Import @Selet 等注解的重要支撑。
    Spring在启动的时候,会从beanFactory中获取继承了beanDefinitionRegisterPostProcessor或beanFactoryPostProcessor类型的beanDefinition对象,并实例化,然后调用里面重写的方法postProcessBeanDefinitionRegistry()

三、registerBeanPostProcessors()
先处理实现了PriorityOrdered的类,然后处理实现了Ordered的类,最后是无顺序的
(
一级缓存:singletonObjects
二级缓存:earlySingletonObjects
三级缓存:singletonFactories
)

1、把实现了BeanPostProcessor接口的类实例化
2、如果实例是MergedBeanDefinitionPostProcessor类型,放入List internalPostProcessors
容器中。
- 如果实例是InstantiationAwareBeanPostProcessor类型,标注hasInstantiationAwareBeanPostProcessors=true
- 如果实例是hasDestructionAwareBeanPostProcessors类型,标注 hasDestructionAwareBeanPostProcessors= true
3、将所有beanpostProcessors的类实例化后放入List beanPostProcessors

四、finishBeanFactoryInitialization(beanFactory)
在这里插入图片描述

  • 一、getSingleton()
    • 1、把beanName添加到singletonsCurrentlyInCreation Set容器中,在这个集合里面的bean都是正在实例化的bean.

      • singletonsCurrentlyInCreation是用来阻断有参构造函数的循环依赖的。
        具体源码位置:beforeSingletonCreation(beanName);
    • 2、调用上层匿名函数(createBean())

      • 1)instanceWrapper = createBeanInstance(){
        • 如果beanDefinition中有factory-method方法
        • BeanWrapper instanceWrapper = createBeanInstance() 该方法实例化bean给一个wrapper
          至此,该bean已经可以通过暴露内存地址被用来使用了
          }
      • 2)applyMergedBeanDefinitionPostProcessors() 对类中注解的装配过程.BeanPostProcessor接口的典型运用,要理解这个接口。
        • 支持了@PostConstruct,@PreDestroy,@Resource,@Autowired,@Value 注解,对这几个注解进行收集。
      • 3)添加三级缓存singletonFactories,
        addSingletonFactory
        (beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        • 这里着重理解,对理解循环依赖帮助非常大。
      • 4)populateBean(beanName, mbd, instanceWrapper) ioc di,Autowire依赖注入的核心方法
        • 实例化已完成
      • 5)exposedObject = initializeBean(beanName, exposedObject, mbd)
        • invokeInitMethod()方法调用,
        • AOP实现入口
        • 类实现了InitializingBean类后,调用类里重写的afterPropertiesSet()逻辑;和init-method属性的调用。
    • 3、bean创建完成后singletonsCurrentlyInCreation容器要删除该bean ,与“一、1”对应。

      • afterSingletonCreation(beanName);
    • 4、实例后的bean放入一级缓存singletonObjects。

  • 二、getObjectForBeanInstance()
    • 实现了FactoryBean接口的类,在上面类实例完和IOC和放入缓存后进行处理。
    • 实现了FactoryBean接口的类,会重写FactoryBean的getObject()方法得到一个类的实例,然后放入到FactoryBeanCache的缓存里。这样autoWire的时候就会调用到。
    • 如果要使用类本身,则用context.getBean(“&factoryBeanDemo”).如果用重写的方法返回的类,用context.getBean(“factoryBeanDemo”)

PS:Autowire注解,日志展示实现过程。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值