文章目录
- 一、前言
- 二、前置准备
- 三、IOC容器的使用
- 四、Spring IOC源码解读
- 1. prepareRefresh源码解读
- 2. obtainFreshBeanFactory源码解读
- 2.1 refreshBeanFactory源码解读
- 3. prepareBeanFactory源码解读
- 4. postProcessBeanFactory源码解读
- 5. invokeBeanFactoryPostProcessors源码解读
- 6. registerBeanPostProcessors源码解读
- 7. initMessageSource源码解析
- 8. initApplicationEventMulticaster源码解读
- 9. onRefresh源码解读
- 10. registerListeners源码解读
- 11. finishBeanFactoryInitialization源码解读
- 11.1 preInstantiateSingletons源码解读
- 12. finishRefresh源码解读
- 13. IOC容器加载失败源码解读
- 14. IOC容器销销毁源码解读
- 五、流程图
一、前言
无论你是一个经验丰富的Java-er
,还是一个Java初学者,都会听过Spring框架的大名,我在初学这个Spring框架的时候都是对这个框架当成一个工具使用,只知道这样做能够达到这样的效果,但是具体里面是怎么实现的也说不清楚,不过随着现在技术的越来越卷,我感觉有必要揭开Spring框架的内幕,深度学习领悟这一优秀的框架了!
本文是针对Spring框架中的IOC
核心功能进行源码解读的,准备好的话,那就一起出发喽
若文章有错误之处,欢迎各位大佬指正!
二、前置准备
本文会对Spring框架的IOC源码进行解读,推荐各位去GitHub下载一份Spring源码配合本篇文章食用更佳!
本文是针对Spring 4.0.0
的源码而编写的,不同版本源码会有差异,但整体业务逻辑不变。
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>4.0.0.RELEASE</version>
</dependency>
不推荐阅读高版本的源码,而更推荐老版本的代码,因为老版本的代码既保留了最初的设计思想,也不会被新出的功能弄得花里胡哨!
三、IOC容器的使用
首先,咱们先来复习一下Spring IOC
容器的使用。
public interface UserService {String selectList();}
public class UserServiceImpl implements UserService {@Overridepublic String selectList() {return "小明, 小红, 小蓝";}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="messageService" class="spring.ioc.UserServiceImpl"/></beans>
public class SpringTest {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");System.out.println("context 启动成功");UserService userService = context.getBean(UserService.class);System.out.println(userService.selectList());}
}
从Spring IOC
的使用中,很直观就能感受到的就是Spring IOC
代替我们程序缘完成了对一个对象的new
把创建实例的工作交给了Spring IOC
,可以简化不少程序员的工作。
这时候有人就说了,
new
一个对象那么简单,用不用Spring IOC
也差不多呀!那不可不是喔,随着系统的迭代开发,一个对象的依赖关系会越来越复杂,比如类A同时依赖类B、类C、类D,而类B又依赖类X、类Y、类Z,当你尝试
new
一个这样的对象不可避免的会感觉心累。。。
四、Spring IOC源码解读
对于Spring IOC
的源码,我认为必须带着“Bean存储在哪?什么时候被实例化?怎么获取的?”
这三个问题去阅读!
还是从上面的Demo代码入手阅读。
public class SpringTest {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");System.out.println("context 启动成功");UserService userService = context.getBean(UserService.class);System.out.println(userService.selectList());}
}
在这个Demo代码中,干了三件事:
- 使用
application.xml
配置文件作为构造参数,创建了一个Spring
容器 - 从
Spring
容器中获取UserService
实例 - 调用
UserService
实例的方法
针对这三步,我合理猜测Spring
容器创建的时候就完成了Spring Bean
的注入。
接下来进入ApplicationContext context = new ClassPathXmlApplicationContext("application.xml")
源码查看是不是这样子的。
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {public ClassPathXmlApplicationContext(String configLocation) throws BeansException {this(new String[] {configLocation}, true, null);}public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)throws BeansException {super(parent);setConfigLocations(configLocations);if (refresh) {refresh();}}}
这里干了三件事:
- 调用了父类
ApplicationContext
的构造函数,并将parent
参数传递给它 - 调用
setConfigLocations
方法,将传入的配置文件路径设置到当前的ClassPathXmlApplicationContext
实例中 - 如果
refresh
为true
,则调用refresh
方法。这个方法会触发Spring容器的刷新过程,重新加载所有的bean定义
其他都不重要,重要的是refresh()
方法,这个方法会触发Spring
容器的刷新,加载Bean的定义。
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();}catch (BeansException ex) {// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}}
}
下面会针对refresh()
的每一步进行解析!
1. prepareRefresh源码解读
prepareRefresh
方法主要是进行Spring
容器刷新前的一些准备工作,并不主要特别关注!
protected void prepareRefresh() {// 记录Spring容器开始刷新的时间this.startupDate = System.currentTimeMillis();// 标志Spring容器刷新工作开始synchronized (this.activeMonitor) {this.active = true;}if (logger.isInfoEnabled()) {logger.info("Refreshing " + this);}// 初始化上下文中的占位符属性源initPropertySources();// 调用getEnvironment方法获取环境对象,并调用其validateRequiredProperties方法来验证必需的属性getEnvironment().validateRequiredProperties();
}
2. obtainFreshBeanFactory源码解读
obtainFreshBeanFactory
的作用是刷新内部Bean工厂返回一个新的BeanFactory
实例。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {refreshBeanFactory();ConfigurableListableBeanFactory beanFactory = getBeanFactory();if (logger.isDebugEnabled()) {logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);}return beanFactory;
}
2.1 refreshBeanFactory源码解读
refreshBeanFactory
是解析application.xml
配置文件并生成BeanDefinition
注册到Spring IOC
中去,具体怎么操作,请看下面org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory
源码解读
protected final void refreshBeanFactory() throws BeansException {// 如果BeanFactory已经存在,先销毁原来的BeanFactoryif (hasBeanFactory()) {destroyBeans();closeBeanFactory();}try {// 创建一个DefaultListableBeanFactoryDefaultListableBeanFactory beanFactory = createBeanFactory();beanFactory.setSerializationId(getId());// 设置bean是否允许覆盖 是否允许循环依赖customizeBeanFactory(beanFactory);// 加载BeanDefinitionloadBeanDefinitions(beanFactory);synchronized (this.beanFactoryMonitor) {this.beanFactory = beanFactory;}}catch (IOException ex) {throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);}
}
DefaultListableBeanFactory
这个类,十分重要!!!它是Spring IOC
容器的核心!!!
org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.support.DefaultListableBeanFactory)
源码如下
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {// 将读取XML操作交付给XmlBeanDefinitionReader,且生成的BeanDefinition注册进IOC中XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);// 设置Spring容器beanDefinitionReader.setEnvironment(this.getEnvironment());beanDefinitionReader.setResourceLoader(this);beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));initBeanDefinitionReader(beanDefinitionReader);// 读取xmlloadBeanDefinitions(beanDefinitionReader);
}
接下来,着重看loadBeanDefinitions(beanDefinitionReader)
,深入了解如何加载BeanDefition
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {// 获取配置资源的数组Resource[] configResources = getConfigResources();if (configResources != null) {reader.loadBeanDefinitions(configResources);}// 配置位置的路径字符串数组,以加载这些路径指定的Bean定义String[] configLocations = getConfigLocations();if (configLocations != null) {reader.loadBeanDefinitions(configLocations);}
}
接着看loadBeanDefinitions
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {Assert.notNull(locations, "Location array must not be null");int count = 0;for (String location : locations) {// 只需要关注loadBeanDefinitions这个方法count += loadBeanDefinitions这个方法(location);}return count;
}
org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.Resource)
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {return loadBeanDefinitions(new EncodedResource(resource));
}public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {/** 省略部分代码 **/return doLoadBeanDefinitions(inputSource, encodedResource.getResource());}
继续看org.springframework.beans.factory.xml.XmlBeanDefinitionReader#doLoadBeanDefinitions
这里开始就是加载BeanDefinitions
了
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)throws BeanDefinitionStoreException {// 因为配置文件是一个xml文件,因此将inputSource进行解析封装成一个DocumentDocument doc = doLoadDocument(inputSource, resource);// 注册Bean定义int count = registerBeanDefinitions(doc, resource);return count;
}
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {// 创建一个DocumentReader, 负责读取和解析XML文档中的Bean定义BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();// 记录加载Bean之前容器的Bean数量int countBefore = getRegistry().getBeanDefinitionCount();// 注册BeandocumentReader.registerBeanDefinitions(doc, createReaderContext(resource));return getRegistry().getBeanDefinitionCount() - countBefore;
}
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#registerBeanDefinitions
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {this.readerContext = readerContext;// 从根元素开始遍历doRegisterBeanDefinitions(doc.getDocumentElement());
}protected void doRegisterBeanDefinitions(Element root) {BeanDefinitionParserDelegate parent = this.delegate;// 创建一个新的BeanDefinitionParserDelegate对象,这个对象将用于解析XML中的bean定义this.delegate = createDelegate(getReaderContext(), root, parent);// 解析Bean定义之前执行一些预处理操作,Spring框架并没有给出实现类, 属于一种扩展点preProcessXml(root);// 重点!!加载Bean定义parseBeanDefinitions(root, this.delegate);// 解析Bean定义之后执行一些后处理操作,Spring框架也并没有给出实现类, 属于一种扩展点postProcessXml(root);this.delegate = parent;
}
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitions
的作用是根据XML配置文件的标签的不同,进行不同的处理
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {if (delegate.isDefaultNamespace(root)) {NodeList nl = root.getChildNodes();for (int i = 0; i < nl.getLength(); i++) {Node node = nl.item(i);if (node instanceof Element) {Element ele = (Element) node;if (delegate.isDefaultNamespace(ele)) {parseDefaultElement(ele, delegate);}else {delegate.parseCustomElement(ele);}}}}else {delegate.parseCustomElement(root);}
}/**
* 根据标签不同进行不同的操作,这里重点介绍processBeanDefinition方法
**/
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {importBeanDefinitionResource(ele);}else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {processAliasRegistration(ele);}else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {// 加载beanprocessBeanDefinition(ele, delegate);}else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {// recursedoRegisterBeanDefinitions(ele);}
}
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#processBeanDefinition
这个方法是将Bean定义注册进容器中
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {// 将XML元素解析成BeanDefinitionHolder对象BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);if (bdHolder != null) {// 对Bean进行适当装饰bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);try {// 将Bean定义注册进容器中BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());}catch (BeanDefinitionStoreException ex) {getReaderContext().error("Failed to register bean definition with name '" +bdHolder.getBeanName() + "'", ele, ex);}// 触发注册时间getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));}
}
debug
进org.springframework.beans.factory.support.BeanDefinitionReaderUtils#registerBeanDefinition
方法,看看是如何进行注册的
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)throws BeanDefinitionStoreException {// 获取Bean定义的名字String beanName = definitionHolder.getBeanName();// 注册Bean定义registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());// 获取别名String[] aliases = definitionHolder.getAliases();if (aliases != null) {for (String alias : aliases) {registry.registerAlias(beanName, alias);}}
}
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException {// 根据BeanName获取BeanDefinitionBeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);if (existingDefinition != null) {// bean已经存在 进行一些操作,感兴趣自己去看源码}else {// BeanName不存在if (hasBeanCreationStarted()) {// Cannot modify startup-time collection elements anymore (for stable iteration)synchronized (this.beanDefinitionMap) {this.beanDefinitionMap.put(beanName, beanDefinition);List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);updatedDefinitions.addAll(this.beanDefinitionNames);updatedDefinitions.add(beanName);this.beanDefinitionNames = updatedDefinitions;removeManualSingletonName(beanName);}}else {// 将beanName与beanDefinition放至beanDefinitionMap中this.beanDefinitionMap.put(beanName, beanDefinition);this.beanDefinitionNames.add(beanName);removeManualSingletonName(beanName);}this.frozenBeanDefinitionNames = null;}
}
到这里BeanDefinition
的注册就基本完成了,主要是以下这些步骤:
- 将XML文件包装成一个
Document
对象 - 利用
BeanDefinitionDocumentReader
解析Document
- 从XML的root进行遍历,针对不同标签
import、bean、beans
等进行不同的处理 - 就
bean
标签而言,在parseBeanDefinitionElement
方法中将bean
标签的组装成一个BeanDefinitionHolder
- 调用
BeanDefinitionRegistry
的registerBeanDefinition
进行BeanDefinition
注册 - 检查
beanName
是否已经注册,如果没有注册则将该BeanDefinition
注册进org.springframework.beans.factory.support.DefaultListableBeanFactory#beanDefinitionMap
中去 - 如果存在别名,也可以进行别名注册。
3. prepareBeanFactory源码解读
prepareBeanFactory
方法主要是完善beanFactory
, 对其进行一些属性填充
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {// 配置类加载器beanFactory.setBeanClassLoader(getClassLoader());// 配置表达式解析器, 用于解析Spring表达式beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());// 注册属性编辑注册器beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));// 添加BeanPostProcessor, 用于处理实现了ApplicationContextAware接口的BeanbeanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));// 忽略特定的依赖接口beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);beanFactory.ignoreDependencyInterface(MessageSourceAware.class);beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);beanFactory.ignoreDependencyInterface(EnvironmentAware.class);// 注册可解析的依赖beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);beanFactory.registerResolvableDependency(ResourceLoader.class, this);beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);beanFactory.registerResolvableDependency(ApplicationContext.class, this);// 检查和准备AOP织入if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));// Set a temporary ClassLoader for type matching.beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}// 注册环境相关beanif (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());}if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());}if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());}
}
4. postProcessBeanFactory源码解读
没有给出实现,交由子类去实现
5. invokeBeanFactoryPostProcessors源码解读
invokeBeanFactoryPostProcessors
的作用是调用所有注册的BeanFactoryPostProcessor
实例
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
}
6. registerBeanPostProcessors源码解读
registerBeanPostProcessors
的作用是实例化BeanPostProcessor
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
}
这里的操作会先把
BeanPostProcessor
创建出来并注入Spring
容器中,但是不会立刻调用BeanPostProcessor
中的方法
7. initMessageSource源码解析
initMessageSource
方法主要是为了初始化Spring框架中的MessageSource
组件——Spring的国际化
protected void initMessageSource() {ConfigurableListableBeanFactory beanFactory = getBeanFactory();if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);// Make MessageSource aware of parent MessageSource.if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;if (hms.getParentMessageSource() == null) {// Only set parent context as parent MessageSource if no parent MessageSource// registered already.hms.setParentMessageSource(getInternalParentMessageSource());}}if (logger.isDebugEnabled()) {logger.debug("Using MessageSource [" + this.messageSource + "]");}}else {// Use empty MessageSource to be able to accept getMessage calls.DelegatingMessageSource dms = new DelegatingMessageSource();dms.setParentMessageSource(getInternalParentMessageSource());this.messageSource = dms;beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);if (logger.isDebugEnabled()) {logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +"': using default [" + this.messageSource + "]");}}
}
什么是Spring国际化?
Spring的国际化(Internationalization,简称i18n)
是指使应用程序能够适应不同语言和地区的过程。国际化的目的是让应用程序能够显示和处理多种语言,从而满足全球用户的需求。Spring框架提供了一套机制来支持国际化
8. initApplicationEventMulticaster源码解读
initApplicationEventMulticaster
的作用是初始化事件广播器,相对比较简单
protected void initApplicationEventMulticaster() {ConfigurableListableBeanFactory beanFactory = getBeanFactory();if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {this.applicationEventMulticaster =beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);if (logger.isDebugEnabled()) {logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");}}else {this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);if (logger.isDebugEnabled()) {logger.debug("Unable to locate ApplicationEventMulticaster with name '" +APPLICATION_EVENT_MULTICASTER_BEAN_NAME +"': using default [" + this.applicationEventMulticaster + "]");}}
}
9. onRefresh源码解读
在Spring中没有给出实现,属于一个模板方法,但是在SpringBoot中启动了Web服务器
protected void onRefresh() throws BeansException {// For subclasses: do nothing by default.
}
10. registerListeners源码解读
registerListeners
的作用是为了注册监听器,方便接收广播事件
protected void registerListeners() {// Register statically specified listeners first.for (ApplicationListener<?> listener : getApplicationListeners()) {getApplicationEventMulticaster().addApplicationListener(listener);}// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let post-processors apply to them!String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);for (String lisName : listenerBeanNames) {getApplicationEventMulticaster().addApplicationListenerBean(lisName);}
}
11. finishBeanFactoryInitialization源码解读
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {// 初始化上下文转化服务,主要用于类型转化、数据转换等等if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));}// 提前实例化LoadTimeWeaverAware的类String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);for (String weaverAwareName : weaverAwareNames) {getBean(weaverAwareName);}// 在BeanFactory初始化完成后,不再需要临时类加载器,因此将其设置为null。beanFactory.setTempClassLoader(null);// BeanFactory将不再期望对Bean的定义进行进一步的更改,这有助于提高性能。beanFactory.freezeConfiguration();// 实例化所有非延迟初始化的单例Bean。这意味着所有剩余的单例Bean都将被创建,即使它们尚未被显式请求。beanFactory.preInstantiateSingletons();
}
11.1 preInstantiateSingletons源码解读
这里的preInstantiateSingletons
是经过简化的
public void preInstantiateSingletons() throws BeansException {List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);for (String beanName : beanNames) {// 获取Bean定义RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);// 需要实例化的bean不是抽象的 并且是单例 并且不属于懒加载if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {if (isFactoryBean(beanName)) {// 获取工厂BeanObject bean = getBean(FACTORY_BEAN_PREFIX + beanName);if (bean instanceof FactoryBean) {FactoryBean<?> factory = (FactoryBean<?>) bean;// 为true表示需要被立刻实例化boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,getAccessControlContext());}else {isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());}if (isEagerInit) {getBean(beanName);}}}else {// 不属于工厂Bean,就可以立即创建BeangetBean(beanName);}}}}
这里干了这几件事情:
- 获取当前所有Bean定义的BeanName集合
- 遍历BeanName集合,进行判断
- 如果该Bean是一个
FactoryBean
,则检查它是否实现了SmartFactoryBean
接口,调用isEagerInit
方法来确定是否需要立即初始化。 - 如果不是
FactoryBean
,立刻实例化
- 如果该Bean是一个
12. finishRefresh源码解读
finishRefresh
的完成容器的启动,清除上下文,初始化生命周期处理器,并发送刷新事件
protected void finishRefresh() {// 初始化生命周期处理器initLifecycleProcessor();// 刷新事件传播到生命周期处理器。getLifecycleProcessor().onRefresh();// 创建并发布一个ContextRefreshedEvent事件,通知所有监听器应用程序上下文已经刷新完成publishEvent(new ContextRefreshedEvent(this));// Participate in LiveBeansView MBean, if active.LiveBeansView.registerApplicationContext(this);
}
13. IOC容器加载失败源码解读
当Spring容器启动的时候出现异常后会走catch
流程,首当其冲就是调用destroyBeans
,也就是销毁所有bean,让JVM能够回收内存。
protected void destroyBeans() {getBeanFactory().destroySingletons();
}public void destroySingletons() {if (logger.isTraceEnabled()) {logger.trace("Destroying singletons in " + this);}synchronized (this.singletonObjects) {this.singletonsCurrentlyInDestruction = true;}String[] disposableBeanNames;synchronized (this.disposableBeans) {disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());}for (int i = disposableBeanNames.length - 1; i >= 0; i--) {destroySingleton(disposableBeanNames[i]);}this.containedBeanMap.clear();this.dependentBeanMap.clear();this.dependenciesForBeanMap.clear();clearSingletonCache();
}public void destroySingletons() {super.destroySingletons();updateManualSingletonNames(Set::clear, set -> !set.isEmpty());clearByTypeCache();
}
接着将IOC容器的活跃状态设置为false
protected void cancelRefresh(BeansException ex) {synchronized (this.activeMonitor) {this.active = false;}
}
14. IOC容器销销毁源码解读
当IOC容器被关闭的时候,会调用close
方法
public void close() {synchronized (this.startupShutdownMonitor) {doClose();}
}
在close
方法调用了doClose
方法
protected void doClose() {boolean actuallyClose;synchronized (this.activeMonitor) {actuallyClose = this.active && !this.closed;this.closed = true;}// 发布容器关闭事件publishEvent(new ContextClosedEvent(this));getLifecycleProcessor().onClose();// 销毁Bean,上面有解释destroyBeans();// 将beanFactory设置为null,方便JVM回收closeBeanFactory();synchronized (this.activeMonitor) {this.active = false;}
}
五、流程图
暂时略~后面有时间再补充哈哈哈