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
- 继承了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);
}
}
- 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);
- singletonsCurrentlyInCreation是用来阻断有参构造函数的循环依赖的。
-
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属性的调用。
- 1)instanceWrapper = createBeanInstance(){
-
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注解,日志展示实现过程。