Spring源码分析之从refresh方法分析Spring的IoC原理


写在前面

Spring Bean 描述了一个 bean 的生命周期,那么这些生命周期中的方法是什么时候执行调用的呢?

refresh() 方法在 ConfigurableApplicationContext 接口中定义,而具体的实现是在 AbstractApplicationContext 中。
refresh() 方法是一个启动方法,调用该方法后,会实例化所有单例以及非单例的对象。

而通过 refresh() ,可以学习到 Spring 是如何初始化 bean 的,分析过程如下:

  1. 怎么处理BeanPostProcessor
  2. 怎么处理InitializingBean
  3. 怎么处理DisposableBean
  4. 怎么处理init-method

refresh

我们先来看看 refresh() :

		public void refresh() throws BeansException, IllegalStateException {
	        synchronized(this.startupShutdownMonitor) {
	        	//刷新加载之前的上下文
	            this.prepareRefresh();
	            //告诉子类刷新内部bean工厂
	            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
	            //准备在上下文中使用的 bean 工厂
	            this.prepareBeanFactory(beanFactory);
	
	            try {
	            	//允许上下文的子类去执行postProcessor
	                this.postProcessBeanFactory(beanFactory);
	                // 开始执行注册到该上下文的BeanFactoryPostProcessors
	                this.invokeBeanFactoryPostProcessors(beanFactory);
	                // 开始注册BeanPostProcessor来拦截其他的bean的初始化过程
	                this.registerBeanPostProcessors(beanFactory);
	                //初始化上下文的消息源
	                this.initMessageSource();
	                //初始化上下文的事件传播器
	                this.initApplicationEventMulticaster();
	                //在特定上下文子类中初始化其他特殊bean
	                this.onRefresh();
	                //检查监听器bean并注册
	                this.registerListeners();
	                //实例化所有剩余的单例
	                this.finishBeanFactoryInitialization(beanFactory);
	                //发布相应的事件
	                this.finishRefresh();
	            } catch (BeansException var9) {
	                if (this.logger.isWarnEnabled()) {
	                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
	                }
	
	                this.destroyBeans();
	                this.cancelRefresh(var9);
	                throw var9;
	            } finally {
	                this.resetCommonCaches();
	            }
	        }
    }

创建 BeanFactory 并解析出 BeanDefinitions

obtainFreshBeanFactory

obtainFreshBeanFactory 方法会实例化 BeanFactory 并加载解析对应的 Bean :
在这里插入图片描述

refreshBeanFactory

初始化 BeanFactory

		protected final void refreshBeanFactory() throws BeansException {
			//如果已经有了一个容器,先销毁里面的bean然后再关闭容器,spring保证只有一个容器
			if (hasBeanFactory()) {
				destroyBeans();
				closeBeanFactory();
			}
			try {
				//创建BeanFactory实例
				DefaultListableBeanFactory beanFactory = createBeanFactory();
				beanFactory.setSerializationId(getId());
				customizeBeanFactory(beanFactory);
				//加载bean
				loadBeanDefinitions(beanFactory);
				//为DefaultListableBeanFactory beanFactory赋值
				synchronized (this.beanFactoryMonitor) {
					this.beanFactory = beanFactory;
				}
			}
			catch (IOException ex) {
				throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
			}
		}
loadBeanDefinitions

是 refreshBeanFactory 中的,用于加载bean
在这里插入图片描述创建一一个XmlBeanDefinitionReader,然后调用 loadBeanDefinitions:

		protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
		String[] configLocations = getConfigLocations();//获取我们的 bean.xml 文件
		if (configLocations != null) {
			for (String configLocation : configLocations) {
				//通过XmlBeanDefinitionReader解析我们的xml文件,初始化BeanDefinition
				reader.loadBeanDefinitions(configLocation);
			}
		}
	}

而初始化后的BeanDefinition放在哪呢?
XmlBeanDefinitionReader 中我们还传入了 beanFactory,看下生成的BeanFactory下的属性:
在这里插入图片描述reader.loadBeanDefinitions(configLocation) 会将解析出来的每个 bean 注册(put)到 beanFactory 中的 beanDefinitionMap 中,registry就是我们存入 beanFactory,而 registerBeanDefinition 方法内部就是调用 map 的 put 方法。
在这里插入图片描述
在这里插入图片描述


getBeanFactory

就是获取 refreshBeanFactory 方法所创建的 BeanFactory
在这里插入图片描述


执行 BeanFactoryPostProcessor 和 BeanPostProcessor

先介绍一下有关的四个接口:

  • beanPostProcessor 这个接口只有两个方法,他允许自定义的去修改spring给我们创建的类。
		public interface BeanPostProcessor {

			Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
		
			Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
		}
  • BeanFactoryPostProcessor 区别于 beanPostProcesso 修改的是当我们初始化Bean的时候,“临时”修改bean的属性,而 beanFactoryPostProcessor 修改的是BeanDefinnition

  • BeanNameAware 实现该接口的bean会意识到自己在beanfactory的的名字

  • BeanFactoryAware 可以在实现BeanFactoryAware的bean中获取beanfactory,也就是获取上下文

而在 refresh() 中与这些接口相关的方法如下:
在这里插入图片描述


invokeBeanFactoryPostProcessors

该方法会先在 BeanDefinition 获取到实现了 BeanFactoryPostProcessor 这个接口的bean的名称:
在这里插入图片描述
这些名称会根据是否实现 Order 等接口分类:
在这里插入图片描述
然后根据 bean 的名称获取到相应的 BeanFactoryPostProcessor ,比如:
在这里插入图片描述

getBean

由上面可知,getBean 方法用于初始化实现BeanFactoryPostProcessor这个接口的bean,实例化好了之后放入List<BeanFactoryPostProcessor>。
在这里插入图片描述

  1. 先在 singleton 缓存中找实例,如果有则直接返回
    在这里插入图片描述
  2. 获取父类 beanFactory,如果有则交给父类来实例化
    在这里插入图片描述
  3. 创建部分:
			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);//标记当前bean正在创建
			}

			try {
				//获取这个bean的beanDefinition
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);
				
				String[] dependsOn = mbd.getDependsOn();//获取这个bean依赖的bean
				if (dependsOn != null) {
					for (String dependsOnBean : dependsOn) {
						if (isDependent(beanName, dependsOnBean)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
						}
						registerDependentBean(dependsOnBean, beanName);
						//创建依赖的 bean,从这可以看出所有 bean 的创建都和 getBean 这个核心方法有关
						getBean(dependsOnBean);
					}
				}

				if (mbd.isSingleton()) {//单例的情况
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
							try {
								//五种域的情况都得调用这个 createBean 方法
								return createBean(beanName, mbd, args);
							}
							catch (BeansException ex) {
								destroySingleton(beanName);
								throw ex;
							}
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
createBean
		protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
			if (logger.isDebugEnabled()) {
				logger.debug("Creating instance of bean '" + beanName + "'");
			}
			RootBeanDefinition mbdToUse = mbd;
			//确保该 bean 的 class 真实存在
			Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
			if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
				mbdToUse = new RootBeanDefinition(mbd);
				mbdToUse.setBeanClass(resolvedClass);
			}
	
			//准备方法的重写
			try {
				mbdToUse.prepareMethodOverrides();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
						beanName, "Validation of method overrides failed", ex);
			}
	
			try {
				// 返回 beanPostProcessor 修改后的bean
				Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
				if (bean != null) {
					return bean;
				}
			}
			catch (Throwable ex) {
				throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
						"BeanPostProcessor before instantiation of bean failed", ex);
			}
	
			//正常创建一个 bean
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isDebugEnabled()) {
				logger.debug("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
doCreateBean

初始化一个 BeanWrapper
在这里插入图片描述
进入createBeanInstance 的 instantiateBean 方法:通过反射使用默认构造器实例化该 bean,此时还没有 setter 赋值。
在这里插入图片描述
回到 doCreateBean : 前面实例化后,这里会开始初始化
在这里插入图片描述
进入 initializeBean 方法: 开始执行 aware 相关方法(BeanFactoryAware 和 BeanNameAware
在这里插入图片描述
在这里插入图片描述进入invokeInitMethods方法: 先判断该 bean 是否实现了 InitializingBean,如果有则执行 afterPropertiesSet,然后再执行 init-method
在这里插入图片描述
在这里插入图片描述


registerBeanPostProcessors

前面我们所说的是实现了 BeanFactoryPostProcessor 接口的bean的初始化过程,那实现了 BeanPostProcessor 接口的bean的初始化呢?是是通过如下的方法:
在这里插入图片描述其实 finishBeanFactoryInitialization 方法初始化的过程和上面是一样的,都是通过 getBean 方法:
在这里插入图片描述
而在执行 invokeInitMethods 的前后就有对 BeanPostProcessor 接口中方法的调用:
在这里插入图片描述


总结

通过上面的分析,可以总结出 Spring 中 Bean 的初始化过程如下:
在这里插入图片描述

发布了96 篇原创文章 · 获赞 57 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/MOKEXFDGH/article/details/100731781