【spring源码解析(一)】

spring源码解析【配置文件——完整bean对象】

流程图

在这里插入图片描述

解析

一,spring是如何加载配置文件到应用程序的?
我们写过xml或者properties等这样的配置文件,那究竟是spring是如何加载的,首先我们从这里去看,想一个问题,各配置文件不同,那么是否需要统一一个规范,去实现读取不同的配置文件?是的,spring提供了这样一个抽象接口,BeanDefinitionReader
在这里插入图片描述
在这个接口下有两个子类,从名字开头相信大家应该能明白了吧,这里要注意源码注释里,BeanDefinitionReader是一个阅读器;读取了这些bean定义信息,它就是一个BeanDefinittion,那么既然是一个阅读器,只是一个阅读,那么想一个问题?我们在xml里定义了一个bean,如下:

<bean id=? class=? >
	<constructor name=username value=${
    
    username}>
	<constructor name=password value=${
    
    password}>
</bean>

这种写法肯定会有人见过,然后再再进行实例化的过程中,那么这个${}怎么办?肯定会变成对应的值,不然没办法做,所以在这里,我们需要知道两个经常面试会问道的问题:BeanFactoryPostProcessor和
BeanPostProcessor之间的区别?BeanFactoryPostProcessor:是处理BeanFactory的,而BeanPostProcessor是处理Bean的;

看到这里,我们再回想一下,读取了这些bean定义信息,它就变成一个BeanDefinition,那么谁来处理
它?
在这里插入图片描述
所以这个过程由BeanFactoryPostProcessor来处理,那么在这个接口一定会有一个子类来处理这些占位符,所以这里出现了一个叫PlaceholderConfigurerSupport的抽象类,其作用就是,解决占位符,来看源码的解释:
在这里插入图片描述接下来实例化bean,再到完整的bean对象,再到销毁,其实也就是我们面试经常会被问到的,bean的生命周期?,源码中有一套标准:
在这里插入图片描述
AbstractApplicationContext这里面,有一个很重要的方法: refresh();里面有13个方法;

@Override
	public void refresh() throws BeansException, IllegalStateException {
    
    
		synchronized (this.startupShutdownMonitor) {
    
    
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

			// Prepare this context for refreshing.
			//准备此上下文以进行刷新
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			//告诉子类刷新内部 bean 工厂。
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			//准备在此上下文中使用的 bean 工厂。
			prepareBeanFactory(beanFactory);

			try {
    
    
				// Allows post-processing of the bean factory in context subclasses.
				//允许在上下文子类中对 bean 工厂进行后处理。
				postProcessBeanFactory(beanFactory);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				// Invoke factory processors registered as beans in the context.
				//调用在上下文中注册为 bean 的工厂处理器。
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				//注册拦截 bean 创建的 bean 处理器。
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();

				// Initialize message source for this context.
				//为此上下文初始化消息源。
				initMessageSource();

				// Initialize event multicaster for this context.
				//为此上下文初始化事件多播器。
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				//初始化特定上下文子类中的其他特殊 bean。
				onRefresh();

				// Check for listener beans and register them.
				//检查侦听器 bean 并注册它们。
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				//实例化所有剩余的(非延迟初始化)单例。
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				//最后一步:发布相应的事件。
				finishRefresh();
			}

			catch (BeansException ex) {
    
    
				if (logger.isWarnEnabled()) {
    
    
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				//销毁已经创建的单例以避免悬空资源。
				destroyBeans();

				// Reset 'active' flag.
				//重置“活动”标志。
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
    
    
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				//重置 Spring 核心中的常见内省缓存
				resetCommonCaches();
				contextRefresh.end();
			}
		}
	}

我们重点来看的是finishBeanFactoryInitialization(beanFactory) 这个方法;
这个方法内有一个:
在这里插入图片描述
是用来实例化剩下的单例的,在这个方法内,会先经过这样一个过程:
在这里插入图片描述
会将beanDefinitionNames放在一个list集合中,循环遍历完成实例化对象,比如xml文件中的两个bean,
其中getMergedLocalBeanDefinition先拿BeanDefinition描述信息,先判断,如果没有拿到,先去创建CreateBean,而真正执行的是doCreateBeancreateBeanInstance 实例化对象,先创建constructorg构造器,然后instantiateBean实例化bean;
在这里插入图片描述
在进入Instantiateclass中有一个ctor.newInstance开始反射,返回的就是相对应的对象,然后在进入populatebean: 其作用就是进行填充对象的属性值
在这里插入图片描述
完了进行aware,再然后就是before,再进行init方法,也就是invokeInitMethods 这个方法:在这里插入图片描述
下一步就是执行after方法,执行完就返回了完整的bean对象;到此大概这个生命周期就是如此,当然还会有销毁的状态,销毁在这里不说。

以上一个大概就是spring中从配置文件读取bean再到bean的一个实例化和初始化的过程,很粗糙,但是希望对大家的一个大概思路有启发,明白了大体思路剩下的细节就慢慢扣吧;

留一个小问题:返回完整的bean对象最终放在哪里了?

猜你喜欢

转载自blog.csdn.net/qq_42990433/article/details/121654729