Spring源码分析——SpringIOC

Spring源码分析——SpringIOC

开始

在Spring中,有两种配置方式,一种是xml版本的,另外一种是注解版本的。他们分别对应不同的ApplicationContext。xml版本的是ClassPathXmlApplicationContext,而注解版本的是AnnotationConfigApplicationContext。

// 用我们的配置文件来启动一个 ApplicationContext
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");

   
   
  • 1
  • 2
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

   
   
  • 1

ApplicationContext子类的构造参数

先看ClassPathXmlApplicationContext的构造方法

org.springframework.context.support.ClassPathXmlApplicationContext#ClassPathXmlApplicationContext(java.lang.String[], boolean, org.springframework.context.ApplicationContext)

	public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {
	<span class="token keyword">super</span><span class="token punctuation">(</span>parent<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token comment">/*简单的把传入进来的配置文件的classpath路径设置到成员变量configLocations中*/</span>
	<span class="token function">setConfigLocations</span><span class="token punctuation">(</span>configLocations<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token keyword">if</span> <span class="token punctuation">(</span>refresh<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
		<span class="token comment">/*核心部分,进行BeanFactory的创建,扫描配置文件加载BeanDefinition,Bean的创建和初始化*/</span>
		<span class="token function">refresh</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

然后就是AnnotationConfigApplicationContext的构造方法

org.springframework.context.annotation.AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(java.lang.Class<?>…)

	public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
		this();
		/**
		 * 解析并注册配置类,也就是我们配置的AppConfig
		 * 解析成BeanDefinition,注册到BeanFactory的成员变量beanDefinitionMap中
		 * 这里的BeanFactory就是DefaultListableBeanFactory
		 */
		register(componentClasses);
		/*核心部分,进行BeanFactory的创建,扫描配置文件加载BeanDefinition,Bean的创建和初始化*/
		refresh();
	}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

可以发现,就是在调用refresh() 方法前做了不同的处理。然后就调用refresh()方法,refresh方法会调用到父类AbstractApplicationContext的refresh方法。

refresh方法时Spring中最重要的方法了
org.springframework.context.support.AbstractApplicationContext#refresh

	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
		<span class="token comment">/**
		 * Prepare this context for refreshing.
		 * 准备工作,设置启动状态,记录系统时间(不重要)
		 */</span>
		<span class="token function">prepareRefresh</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

		<span class="token comment">/**
		 * 创建DefaultListableBeanFactory,
		 * 扫描并注册BeanDefinition到BeanDefinitionMap中,
		 * 返回这个BeanFactory
		 * 注意:
		 * 	如果是注解的bean,不会在这里注册BeanDefinition到BeanDefinitionMap
		 * 	而是在下面的invokeBeanFactoryPostProcessors里,通过bean工厂后置处理器完成
		 */</span>
		ConfigurableListableBeanFactory beanFactory <span class="token operator">=</span> <span class="token function">obtainFreshBeanFactory</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

		<span class="token comment">/**
		 * 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
		 */</span>
		<span class="token function">prepareBeanFactory</span><span class="token punctuation">(</span>beanFactory<span class="token punctuation">)</span><span class="token punctuation">;</span>

		<span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span>
			<span class="token comment">// 这个是留给ApplicationContext子类的扩展点,允许在子类中对bean工厂进行后处理。</span>
			<span class="token function">postProcessBeanFactory</span><span class="token punctuation">(</span>beanFactory<span class="token punctuation">)</span><span class="token punctuation">;</span>

			StartupStep beanPostProcess <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>applicationStartup<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token string">"spring.context.beans.post-process"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token comment">// 调用上下文中注册为bean的工厂处理器。</span>
			<span class="token function">invokeBeanFactoryPostProcessors</span><span class="token punctuation">(</span>beanFactory<span class="token punctuation">)</span><span class="token punctuation">;</span>

			<span class="token comment">// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别</span>
			<span class="token comment">// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization</span>
			<span class="token comment">// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化</span>
			<span class="token function">registerBeanPostProcessors</span><span class="token punctuation">(</span>beanFactory<span class="token punctuation">)</span><span class="token punctuation">;</span>
			beanPostProcess<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

			<span class="token comment">// 初始化当前 ApplicationContext 的 MessageSource,国际化</span>
			<span class="token function">initMessageSource</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

			<span class="token comment">// 初始化当前 ApplicationContext 的事件广播器</span>
			<span class="token function">initApplicationEventMulticaster</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

			<span class="token comment">// 从方法名就可以知道,典型的模板方法(钩子方法),</span>
			<span class="token comment">// 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)</span>
			<span class="token function">onRefresh</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

			<span class="token comment">// 注册事件监听器,监听器需要实现 ApplicationListener 接口</span>
			<span class="token function">registerListeners</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

			<span class="token comment">/**
			 * 重点方法:
			 * 初始化所有的 singleton beans
			 */</span>
			<span class="token function">finishBeanFactoryInitialization</span><span class="token punctuation">(</span>beanFactory<span class="token punctuation">)</span><span class="token punctuation">;</span>

			<span class="token comment">// 最后,广播事件,ApplicationContext 初始化完成</span>
			<span class="token function">finishRefresh</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>

		<span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">BeansException</span> ex<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			<span class="token keyword">if</span> <span class="token punctuation">(</span>logger<span class="token punctuation">.</span><span class="token function">isWarnEnabled</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
				logger<span class="token punctuation">.</span><span class="token function">warn</span><span class="token punctuation">(</span><span class="token string">"Exception encountered during context initialization - "</span> <span class="token operator">+</span>
						<span class="token string">"cancelling refresh attempt: "</span> <span class="token operator">+</span> ex<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span>

			<span class="token comment">// Destroy already created singletons to avoid dangling resources.</span>
			<span class="token function">destroyBeans</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

			<span class="token comment">// Reset 'active' flag.</span>
			<span class="token function">cancelRefresh</span><span class="token punctuation">(</span>ex<span class="token punctuation">)</span><span class="token punctuation">;</span>

			<span class="token comment">// Propagate exception to caller.</span>
			<span class="token keyword">throw</span> ex<span class="token punctuation">;</span>
		<span class="token punctuation">}</span>

		<span class="token keyword">finally</span> <span class="token punctuation">{<!-- --></span>
			<span class="token comment">// Reset common introspection caches in Spring's core, since we</span>
			<span class="token comment">// might not ever need metadata for singleton beans anymore...</span>
			<span class="token function">resetCommonCaches</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			contextRefresh<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87

上面的方法没必要全都看,我们分析IOC,主要看3个方法就够了

  1. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 这个是BeanFactory的创建,以及解析配置文件,加载BeanDefinition
  2. invokeBeanFactoryPostProcessors(beanFactory); 这个是触发Bean工厂后置处理器的回调
  3. finishBeanFactoryInitialization(beanFactory); 这个是实例化和初始化所有的bean

BeanFactory的创建,加载BeanDefinition

我们先来看refresh方法中第一个要分析的方法

			/**
			 * 创建DefaultListableBeanFactory,
			 * 扫描并注册BeanDefinition到BeanDefinitionMap中,
			 * 返回这个BeanFactory
			 * 注意:
			 * 	如果是注解的bean,不会在这里注册BeanDefinition到BeanDefinitionMap
			 * 	而是在下面的invokeBeanFactoryPostProcessors里,通过bean工厂后置处理器完成
			 */
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

这个方法里面会创建BeanFactory,具体类型是DefaultListableBeanFactory。并且在创建了DefaultListableBeanFactory之后,会进行配置文件的解析工作,加载BeanDefinition,注册到DefaultListableBeanFactory的beanDefinitionMap中

org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory

	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		/* 销毁旧的BeanFactory,创建新的BeanFactory并扫描注册BeanDefinition */
		refreshBeanFactory();
		/* 获取并返回创建的BeanFactory */
		return getBeanFactory();
	}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

上面方法分两步

  1. 刷新BeanFactory,也就是销毁旧的BeanFactory,创建新的BeanFactory。然后还会加载BeanDefinition
  2. 获取并返回BeanFactory

我们只要看第一步就可以,因为第一步走完以后,BeanFactory就已经保存在AbstractRefreshableApplicationContext的成员变量中了,也就是当前ApplicationContext实现类的父类的成员变量,所以只是返回成员变量而已。

org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory

	@Override
	protected final void refreshBeanFactory() throws BeansException {
		/**
		 * 检查当前ApplicationContext是否已经有启动的BeanFactory
		 * 如果有,则销毁Bean,关闭BeanFactory
		 */
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			/*创建DefaultListableBeanFactory*/
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			/*设置BeanFactory的两个属性:是否允许 Bean 覆盖、是否允许循环引用*/
			customizeBeanFactory(beanFactory);
			/*加载 BeanDefinition 到 BeanFactory 中*/
			loadBeanDefinitions(beanFactory);
			/*保存此BeanFactory到成员变量*/
			this.beanFactory = beanFactory;
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  1. 先销毁所有的bean,关闭旧的工厂
  2. 创建DefaultListableBeanFactory
  3. 设置两个重要的属性到DefaultListableBeanFactory中:allowBeanDefinitionOverriding-是否允许Bean覆盖,allowCircularReferences-是否允许循环依赖
  4. 加载BeanDefinition

我们直接看的4步,BeanDefinition的加载

org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.support.DefaultListableBeanFactory)

	@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		/**
		 * Create a new XmlBeanDefinitionReader for the given BeanFactory.
		 * 创建XmlBeanDefinitionReader,他的功能是解析配置文件并加载BeanDefinition
		 */
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
	<span class="token comment">// Configure the bean definition reader with this context's</span>
	<span class="token comment">// resource loading environment.</span>
	beanDefinitionReader<span class="token punctuation">.</span><span class="token function">setEnvironment</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getEnvironment</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	beanDefinitionReader<span class="token punctuation">.</span><span class="token function">setResourceLoader</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	beanDefinitionReader<span class="token punctuation">.</span><span class="token function">setEntityResolver</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">ResourceEntityResolver</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token comment">// Allow a subclass to provide custom initialization of the reader,</span>
	<span class="token comment">// then proceed with actually loading the bean definitions.</span>
	<span class="token function">initBeanDefinitionReader</span><span class="token punctuation">(</span>beanDefinitionReader<span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token comment">/* 解析配置文件,加载并注册BeanDefinition */</span>
	<span class="token function">loadBeanDefinitions</span><span class="token punctuation">(</span>beanDefinitionReader<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  1. 创建一个XmlBeanDefinitionReader,很明显到时候xml配置文件就是通过他来解析
  2. loadBeanDefinitions(beanDefinitionReader); 解析配置文件,加载并注册BeanDefinition

这里直接看最后一步
org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.xml.XmlBeanDefinitionReader)

	protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		/**
		 * 当前如果已经有加载的Resource,则先进行前期BeanDefinition的加载
		 * 一般是扩展的子ApplicationContext预设的BeanDefinition
		 * 这里为空,所以先不走
		 */
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			reader.loadBeanDefinitions(configResources);
		}
		/**
		 * 这里是读取配置文件成Resource,并解析加载BeanDefinition的步骤,
		 * 会走到上面的loadBeanDefinitions(Resource...)方法
		 */
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
	}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

这里有两个分支

  • 如果当有加载了的Resource,则先走上面一个分支,进行预设的配置加载
  • 如果没有预设的Resource,则走下面一步,读取配置文件成Resource对象

但是其实下面一步走后还是会走到上面的方法中。这里一进来,会先走下面一个分支,因为现在没有任何预先加载的Resource对象

org.springframework.beans.factory.support.AbstractBeanDefinitionReader#loadBeanDefinitions(java.lang.String…)

	@Override
	public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
		Assert.notNull(locations, "Location array must not be null");
		int count = 0;
		for (String location : locations) {
			/*遍历配置文件路径,并一个个加载解析*/
			count += loadBeanDefinitions(location);
		}
		return count;
	}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

这里会遍历所有的配置文件路径,解析配置文件。但是我们只传入了一个,通常也只会传入一个,所以这里可以当成是一个配置文件的解析,循环只会走一遍。

org.springframework.beans.factory.support.AbstractBeanDefinitionReader#loadBeanDefinitions(java.lang.String, java.util.Set<org.springframework.core.io.Resource>)

	public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
		ResourceLoader resourceLoader = getResourceLoader();
		...
		if (resourceLoader instanceof ResourcePatternResolver) {
			try {
				/*读取当前的xml配置文件,成一个resources数组*/
				Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
				/*走到之前的loadBeanDefinitions(Resource...)方法,解析Resource成BeanDefinition*/
				int count = loadBeanDefinitions(resources);
				...
				return count;
			}
			catch (IOException ex) {
				...
			}
		}
		else {
			...
		}
	}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  1. 读取当前的xml配置文件,成一个resources数组
  2. 解析Resource,加载BeanDefinition。这里会走到之前loadBeanDefinitions方法的上面一个分支里的方法

我们直接看第二步

org.springframework.beans.factory.support.AbstractBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.Resource…)

	@Override
	public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
		Assert.notNull(resources, "Resource array must not be null");
		int count = 0;
		for (Resource resource : resources) {
			/*遍历解析Resource,加载BeanDefinition*/
			count += loadBeanDefinitions(resource);
		}
		return count;
	}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

遍历Resource,并调用loadBeanDefinitions的另外一个重载的方法,也就是刚刚进来跳过没走的那个分支。

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.Resource)

	@Override
	public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
		/*把resouce封装成EncodedResource*/
		return loadBeanDefinitions(new EncodedResource(resource));
	}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5

有调了loadBeanDefinitions的另外一个重载的方法,继续点进去

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.support.EncodedResource)

	public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		...
	Set<span class="token generics function"><span class="token punctuation">&lt;</span>EncodedResource<span class="token punctuation">&gt;</span></span> currentResources <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>resourcesCurrentlyBeingLoaded<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
	<span class="token comment">/**
	 * 获取当前配置文件的输入流,封装成InputSource
	 * 并执行BeanDefinitions的加载
	 */</span>
	<span class="token keyword">try</span> <span class="token punctuation">(</span>InputStream inputStream <span class="token operator">=</span> encodedResource<span class="token punctuation">.</span><span class="token function">getResource</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getInputStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
		InputSource inputSource <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">InputSource</span><span class="token punctuation">(</span>inputStream<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>encodedResource<span class="token punctuation">.</span><span class="token function">getEncoding</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">!=</span> null<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			inputSource<span class="token punctuation">.</span><span class="token function">setEncoding</span><span class="token punctuation">(</span>encodedResource<span class="token punctuation">.</span><span class="token function">getEncoding</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
		<span class="token comment">/*真正开始BeanDefinition的加载,在spring中,但凡是doxxx的方法,代表要真正开始,而前面都是铺垫*/</span>
		<span class="token keyword">return</span> <span class="token function">doLoadBeanDefinitions</span><span class="token punctuation">(</span>inputSource<span class="token punctuation">,</span> encodedResource<span class="token punctuation">.</span><span class="token function">getResource</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">IOException</span> ex<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
		<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
	<span class="token punctuation">}</span>
	<span class="token keyword">finally</span> <span class="token punctuation">{<!-- --></span>
		currentResources<span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span>encodedResource<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>currentResources<span class="token punctuation">.</span><span class="token function">isEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			<span class="token keyword">this</span><span class="token punctuation">.</span>resourcesCurrentlyBeingLoaded<span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

这里要调用doLoadBeanDefinitions方法,开始真正的BeanDefinition加载工作

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#doLoadBeanDefinitions

	protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
	<span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span>
		<span class="token comment">/*解析成Document对象*/</span>
		Document doc <span class="token operator">=</span> <span class="token function">doLoadDocument</span><span class="token punctuation">(</span>inputSource<span class="token punctuation">,</span> resource<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token comment">/*执行BeanDefinition的解析注册*/</span>
		<span class="token keyword">int</span> count <span class="token operator">=</span> <span class="token function">registerBeanDefinitions</span><span class="token punctuation">(</span>doc<span class="token punctuation">,</span> resource<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>logger<span class="token punctuation">.</span><span class="token function">isDebugEnabled</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			logger<span class="token punctuation">.</span><span class="token function">debug</span><span class="token punctuation">(</span><span class="token string">"Loaded "</span> <span class="token operator">+</span> count <span class="token operator">+</span> <span class="token string">" bean definitions from "</span> <span class="token operator">+</span> resource<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
		<span class="token keyword">return</span> count<span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token keyword">catch</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  1. 解析配置文件,获取Document对象
  2. 根据Document对象,加载BeanDefinition

我们看第二步

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinitions

	public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		/*创建BeanDefinitionDocumentReader对象*/
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		int countBefore = getRegistry().getBeanDefinitionCount();
		/*解析Document并注册BeanDefinition*/
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  1. 创建BeanDefinitionDocumentReader对象
  2. 解析Document并注册BeanDefinition

我们看第二步

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#registerBeanDefinitions

	@Override
	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		/*获取Document中的Element节点(root)并解析*/
		doRegisterBeanDefinitions(doc.getDocumentElement());
	}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

获取根节点,并从根节点开始解析

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions

	protected void doRegisterBeanDefinitions(Element root) {
		// 我们看名字就知道,BeanDefinitionParserDelegate 必定是一个重要的类,它负责解析 Bean 定义,
		// 这里为什么要定义一个 parent? 看到后面就知道了,是递归问题,
		// 因为 <beans /> 内部是可以定义 <beans /> 的,所以这个方法的 root 其实不一定就是 xml 的根节点,也可以是嵌套在里面的 <beans /> 节点,
		// 从源码分析的角度,我们当做根节点就好了
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(getReaderContext(), root, parent);
	<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>delegate<span class="token punctuation">.</span><span class="token function">isDefaultNamespace</span><span class="token punctuation">(</span>root<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
		String profileSpec <span class="token operator">=</span> root<span class="token punctuation">.</span><span class="token function">getAttribute</span><span class="token punctuation">(</span>PROFILE_ATTRIBUTE<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>StringUtils<span class="token punctuation">.</span><span class="token function">hasText</span><span class="token punctuation">(</span>profileSpec<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			String<span class="token punctuation">[</span><span class="token punctuation">]</span> specifiedProfiles <span class="token operator">=</span> StringUtils<span class="token punctuation">.</span><span class="token function">tokenizeToStringArray</span><span class="token punctuation">(</span>
					profileSpec<span class="token punctuation">,</span> BeanDefinitionParserDelegate<span class="token punctuation">.</span>MULTI_VALUE_ATTRIBUTE_DELIMITERS<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token comment">// We cannot use Profiles.of(...) since profile expressions are not supported</span>
			<span class="token comment">// in XML config. See SPR-12458 for details.</span>
			<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">getReaderContext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getEnvironment</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">acceptsProfiles</span><span class="token punctuation">(</span>specifiedProfiles<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
				<span class="token keyword">if</span> <span class="token punctuation">(</span>logger<span class="token punctuation">.</span><span class="token function">isDebugEnabled</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
					logger<span class="token punctuation">.</span><span class="token function">debug</span><span class="token punctuation">(</span><span class="token string">"Skipped XML bean definition file due to specified profiles ["</span> <span class="token operator">+</span> profileSpec <span class="token operator">+</span>
							<span class="token string">"] not matching: "</span> <span class="token operator">+</span> <span class="token function">getReaderContext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getResource</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
				<span class="token punctuation">}</span>
				<span class="token keyword">return</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span>

	<span class="token function">preProcessXml</span><span class="token punctuation">(</span>root<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token comment">/*通过BeanDefinitionParserDelegate解析当前节点*/</span>
	<span class="token function">parseBeanDefinitions</span><span class="token punctuation">(</span>root<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>delegate<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token function">postProcessXml</span><span class="token punctuation">(</span>root<span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token keyword">this</span><span class="token punctuation">.</span>delegate <span class="token operator">=</span> parent<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

我们直接看parseBeanDefinitions(root, this.delegate);,其他的忽略

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitions

	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);
		}
	}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

这里有两种情况

  • 默认标签的解析,就是spring原生的标签
  • 自定义标签的解析,就是其他和spring做整合的框架提供的标签

我们看默认标签的解析

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseDefaultElement

	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)) {
			/*<bean/>解析*/
			processBeanDefinition(ele, delegate);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

这里涉及四种标签的解析,我们只看最简单的bean标签的解析

	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		/*解析当前bean节点为为BeanDefinition,并用BeanDefinitionHolder进行包装*/
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				/**
				 * 里面会调用到DefaultListableBeanFactory的registerBeanDefinition重写方法
				 * 把该BeanDefinition注册到DefaultListableBeanFactory的成员变量beanDefinitionMap中
				 * this.beanDefinitionMap.put(beanName, beanDefinition);
				 */
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				...
			}
			...
		}
	}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

processBeanDefinition方法中,当前的流程分两步

  1. 解析当前bean节点为为BeanDefinition,并用BeanDefinitionHolder进行包装
  2. 把BeanDefinition注册到DefaultListableBeanFactory的成员变量beanDefinitionMap中

我们先看第一步

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionElement(org.w3c.dom.Element)

	@Nullable
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
		return parseBeanDefinitionElement(ele, null);
	}

 
 
  • 1
  • 2
  • 3
  • 4

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)

	@Nullable
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
		String id = ele.getAttribute(ID_ATTRIBUTE);
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
	List<span class="token generics function"><span class="token punctuation">&lt;</span>String<span class="token punctuation">&gt;</span></span> aliases <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ArrayList</span><span class="token operator">&lt;</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token comment">// 将 name 属性的定义按照 ”逗号、分号、空格“ 切分,形成一个别名列表数组,</span>
	<span class="token keyword">if</span> <span class="token punctuation">(</span>StringUtils<span class="token punctuation">.</span><span class="token function">hasLength</span><span class="token punctuation">(</span>nameAttr<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
		String<span class="token punctuation">[</span><span class="token punctuation">]</span> nameArr <span class="token operator">=</span> StringUtils<span class="token punctuation">.</span><span class="token function">tokenizeToStringArray</span><span class="token punctuation">(</span>nameAttr<span class="token punctuation">,</span> MULTI_VALUE_ATTRIBUTE_DELIMITERS<span class="token punctuation">)</span><span class="token punctuation">;</span>
		aliases<span class="token punctuation">.</span><span class="token function">addAll</span><span class="token punctuation">(</span>Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span>nameArr<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	String beanName <span class="token operator">=</span> id<span class="token punctuation">;</span>
	<span class="token comment">// 如果没有指定id, 那么用别名列表的第一个名字作为beanName</span>
	<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>StringUtils<span class="token punctuation">.</span><span class="token function">hasText</span><span class="token punctuation">(</span>beanName<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span>aliases<span class="token punctuation">.</span><span class="token function">isEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
		beanName <span class="token operator">=</span> aliases<span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
	<span class="token punctuation">}</span>

	<span class="token keyword">if</span> <span class="token punctuation">(</span>containingBean <span class="token operator">==</span> null<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
		<span class="token function">checkNameUniqueness</span><span class="token punctuation">(</span>beanName<span class="token punctuation">,</span> aliases<span class="token punctuation">,</span> ele<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token comment">// 根据 &lt;bean ...&gt;...&lt;/bean&gt; 中的配置创建 BeanDefinition,然后把配置中的信息都设置到实例中</span>
	AbstractBeanDefinition beanDefinition <span class="token operator">=</span> <span class="token function">parseBeanDefinitionElement</span><span class="token punctuation">(</span>ele<span class="token punctuation">,</span> beanName<span class="token punctuation">,</span> containingBean<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token comment">// 到这里,整个 &lt;bean /&gt; 标签就算解析结束了,一个 BeanDefinition 就形成了</span>
	<span class="token keyword">if</span> <span class="token punctuation">(</span>beanDefinition <span class="token operator">!=</span> null<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
		<span class="token comment">// 如果都没有设置 id 和 name,那么此时的 beanName 就会为 null,进入下面这块代码产生</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>StringUtils<span class="token punctuation">.</span><span class="token function">hasText</span><span class="token punctuation">(</span>beanName<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			<span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span>
				<span class="token keyword">if</span> <span class="token punctuation">(</span>containingBean <span class="token operator">!=</span> null<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
					beanName <span class="token operator">=</span> BeanDefinitionReaderUtils<span class="token punctuation">.</span><span class="token function">generateBeanName</span><span class="token punctuation">(</span>
							beanDefinition<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>readerContext<span class="token punctuation">.</span><span class="token function">getRegistry</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
				<span class="token punctuation">}</span>
				<span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
					beanName <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>readerContext<span class="token punctuation">.</span><span class="token function">generateBeanName</span><span class="token punctuation">(</span>beanDefinition<span class="token punctuation">)</span><span class="token punctuation">;</span>
					String beanClassName <span class="token operator">=</span> beanDefinition<span class="token punctuation">.</span><span class="token function">getBeanClassName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
					<span class="token keyword">if</span> <span class="token punctuation">(</span>beanClassName <span class="token operator">!=</span> null <span class="token operator">&amp;&amp;</span>
							beanName<span class="token punctuation">.</span><span class="token function">startsWith</span><span class="token punctuation">(</span>beanClassName<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> beanName<span class="token punctuation">.</span><span class="token function">length</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&gt;</span> beanClassName<span class="token punctuation">.</span><span class="token function">length</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span>
							<span class="token operator">!</span><span class="token keyword">this</span><span class="token punctuation">.</span>readerContext<span class="token punctuation">.</span><span class="token function">getRegistry</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">isBeanNameInUse</span><span class="token punctuation">(</span>beanClassName<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
						aliases<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>beanClassName<span class="token punctuation">)</span><span class="token punctuation">;</span>
					<span class="token punctuation">}</span>
				<span class="token punctuation">}</span>
				<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
			<span class="token punctuation">}</span>
			<span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> ex<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
			<span class="token punctuation">}</span>
		<span class="token punctuation">}</span>
		String<span class="token punctuation">[</span><span class="token punctuation">]</span> aliasesArray <span class="token operator">=</span> StringUtils<span class="token punctuation">.</span><span class="token function">toStringArray</span><span class="token punctuation">(</span>aliases<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token comment">// 返回 BeanDefinitionHolder</span>
		<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">BeanDefinitionHolder</span><span class="token punctuation">(</span>beanDefinition<span class="token punctuation">,</span> beanName<span class="token punctuation">,</span> aliasesArray<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token keyword">return</span> null<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

这里重点方法就是中间的 AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); 其他可以不用看。这里就是Bean标签的解析,BeanDefinition的加载,
然后返回的BeanDefinition在最后被包装成BeanDefinitionHolder返回

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionElement(org.w3c.dom.Element, java.lang.String, org.springframework.beans.factory.config.BeanDefinition)

	@Nullable
	public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, @Nullable BeanDefinition containingBean) {
	<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>

	<span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span>
		<span class="token comment">// 创建 BeanDefinition</span>
		AbstractBeanDefinition bd <span class="token operator">=</span> <span class="token function">createBeanDefinition</span><span class="token punctuation">(</span>className<span class="token punctuation">,</span> parent<span class="token punctuation">)</span><span class="token punctuation">;</span>

		<span class="token comment">// 设置 BeanDefinition 的一堆属性,这些属性定义在 AbstractBeanDefinition 中</span>
		<span class="token function">parseBeanDefinitionAttributes</span><span class="token punctuation">(</span>ele<span class="token punctuation">,</span> beanName<span class="token punctuation">,</span> containingBean<span class="token punctuation">,</span> bd<span class="token punctuation">)</span><span class="token punctuation">;</span>
		bd<span class="token punctuation">.</span><span class="token function">setDescription</span><span class="token punctuation">(</span>DomUtils<span class="token punctuation">.</span><span class="token function">getChildElementValueByTagName</span><span class="token punctuation">(</span>ele<span class="token punctuation">,</span> DESCRIPTION_ELEMENT<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

		<span class="token comment">/**
		 * 下面的一堆是解析 &lt;bean&gt;......&lt;/bean&gt; 内部的子元素,
		 * 解析出来以后的信息都放到 bd 的属性中
		 */</span>

		<span class="token comment">// 解析 &lt;meta /&gt;</span>
		<span class="token function">parseMetaElements</span><span class="token punctuation">(</span>ele<span class="token punctuation">,</span> bd<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token comment">// 解析 &lt;lookup-method /&gt;</span>
		<span class="token function">parseLookupOverrideSubElements</span><span class="token punctuation">(</span>ele<span class="token punctuation">,</span> bd<span class="token punctuation">.</span><span class="token function">getMethodOverrides</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token comment">// 解析 &lt;replaced-method /&gt;</span>
		<span class="token function">parseReplacedMethodSubElements</span><span class="token punctuation">(</span>ele<span class="token punctuation">,</span> bd<span class="token punctuation">.</span><span class="token function">getMethodOverrides</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token comment">// 解析 &lt;constructor-arg /&gt;</span>
		<span class="token function">parseConstructorArgElements</span><span class="token punctuation">(</span>ele<span class="token punctuation">,</span> bd<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token comment">// 解析 &lt;property /&gt;</span>
		<span class="token function">parsePropertyElements</span><span class="token punctuation">(</span>ele<span class="token punctuation">,</span> bd<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token comment">// 解析 &lt;qualifier /&gt;</span>
		<span class="token function">parseQualifierElements</span><span class="token punctuation">(</span>ele<span class="token punctuation">,</span> bd<span class="token punctuation">)</span><span class="token punctuation">;</span>

		bd<span class="token punctuation">.</span><span class="token function">setResource</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>readerContext<span class="token punctuation">.</span><span class="token function">getResource</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		bd<span class="token punctuation">.</span><span class="token function">setSource</span><span class="token punctuation">(</span><span class="token function">extractSource</span><span class="token punctuation">(</span>ele<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

		<span class="token keyword">return</span> bd<span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token keyword">catch</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>

	<span class="token keyword">return</span> null<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

可以看到这里要进行标签的解析了,包括bean标签本身的属性(id,name,class,scope,是否懒加载…),以及他嵌套的其他标签

细枝末节就不看了,bean标签的解析看到这里接续,这里就会返回BeanDefinition,然后再外面就被包装为BeanDefinitionHolder返回了

然后回到processBeanDefinition方法中,看第二步,就是把BeanDefinition注册到DefaultListableBeanFactory的成员变量beanDefinitionMap中

/**
 * 里面会调用到DefaultListableBeanFactory的registerBeanDefinition重写方法
 * 把该BeanDefinition注册到DefaultListableBeanFactory的成员变量beanDefinitionMap中
 * this.beanDefinitionMap.put(beanName, beanDefinition);
 */
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

org.springframework.beans.factory.support.BeanDefinitionReaderUtils#registerBeanDefinition

	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {
	<span class="token comment">// 获取该BeanDefinition的beanName</span>
	String beanName <span class="token operator">=</span> definitionHolder<span class="token punctuation">.</span><span class="token function">getBeanName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token comment">// 注册这个 Bean</span>
	registry<span class="token punctuation">.</span><span class="token function">registerBeanDefinition</span><span class="token punctuation">(</span>beanName<span class="token punctuation">,</span> definitionHolder<span class="token punctuation">.</span><span class="token function">getBeanDefinition</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token comment">// 如果还有别名的话,也要根据别名统统注册一遍</span>
	String<span class="token punctuation">[</span><span class="token punctuation">]</span> aliases <span class="token operator">=</span> definitionHolder<span class="token punctuation">.</span><span class="token function">getAliases</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token keyword">if</span> <span class="token punctuation">(</span>aliases <span class="token operator">!=</span> null<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
		<span class="token keyword">for</span> <span class="token punctuation">(</span>String alias <span class="token operator">:</span> aliases<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			registry<span class="token punctuation">.</span><span class="token function">registerAlias</span><span class="token punctuation">(</span>beanName<span class="token punctuation">,</span> alias<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

这里会获取beanName作为key,BeanDefinition作为value,进行注册。下面是注册别名。

我们直接看Bean的注册

org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition

	@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {
	<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
	
	<span class="token comment">/*查看此beanName是否已有注册的BeanDefinition*/</span>
	BeanDefinition existingDefinition <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>beanDefinitionMap<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>beanName<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token keyword">if</span> <span class="token punctuation">(</span>existingDefinition <span class="token operator">!=</span> null<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
		<span class="token comment">/*如果“允许BeanDefinition覆盖”属性为false,则抛出异常*/</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">isAllowBeanDefinitionOverriding</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">BeanDefinitionOverrideException</span><span class="token punctuation">(</span>beanName<span class="token punctuation">,</span> beanDefinition<span class="token punctuation">,</span> existingDefinition<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
		<span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>existingDefinition<span class="token punctuation">.</span><span class="token function">getRole</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&lt;</span> beanDefinition<span class="token punctuation">.</span><span class="token function">getRole</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
		<span class="token punctuation">}</span>
		<span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>beanDefinition<span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>existingDefinition<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
		<span class="token punctuation">}</span>
		<span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
			<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
		<span class="token punctuation">}</span>
		<span class="token comment">/* 注册BeanDefinition,其实就是放到一个map中 */</span>
		<span class="token keyword">this</span><span class="token punctuation">.</span>beanDefinitionMap<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span>beanName<span class="token punctuation">,</span> beanDefinition<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">hasBeanCreationStarted</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
		<span class="token punctuation">}</span>
		<span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
			<span class="token comment">// 最正常的应该是进到这里。</span>
			<span class="token comment">// 将 BeanDefinition 放到这个 map 中</span>
			<span class="token keyword">this</span><span class="token punctuation">.</span>beanDefinitionMap<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span>beanName<span class="token punctuation">,</span> beanDefinition<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token comment">// 这是个 ArrayList,所以会按照 bean 配置的顺序保存每一个注册的 Bean 的名字</span>
			<span class="token keyword">this</span><span class="token punctuation">.</span>beanDefinitionNames<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>beanName<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token function">removeManualSingletonName</span><span class="token punctuation">(</span>beanName<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
		<span class="token keyword">this</span><span class="token punctuation">.</span>frozenBeanDefinitionNames <span class="token operator">=</span> null<span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

可以看到调用的是DefaultListableBeanFactory重写的方法,this.beanDefinitionMap.put(beanName, beanDefinition); 就是把BeanDefinition放到成员变量beanDefinitionMap,他就是一个Map。

然后依次类推加载完成所有的标签,然后就会返回创建好的DefaultListableBeanFactory,此时他已经报错了所有的BeanDefinition,除了注解方式声明的Bean。因为在AnnotationConfigApplicationContext是没有xml配置文件的,我们传递给他的构造函数的参数是一个配置类的class,他只会在refresh方法执行前先加载这个类,变成BeanDefinition,另外的Bean,要等到refresh方法中的下一步 invokeBeanFactoryPostProcessors(beanFactory); 当中完成。这个也是 AnnotationConfigApplicationContext 和 ClassPathXmlApplicationContext 的另外一个不同点。实际上他们俩的不同,仅限于在配置文件到BeanDefinition的阶段,由BeanDefinition到Bean(也就是Bean的实例化和初始化)这个阶段,他们的逻辑是一样的,因为都是调用父类的方法。

调用上下文中注册为bean的工厂处理器

BeanFactory的创建和BeanDefinition的加载完毕以后,回到refresh方法中,这是已经返回了beanFactory,以ConfigurableListableBeanFactory类型接收。后面会走以下两步方法

// 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
prepareBeanFactory(beanFactory);

 
 
  • 1
  • 2
// 这个是留给ApplicationContext子类的扩展点,允许在子类中对bean工厂进行后处理。
postProcessBeanFactory(beanFactory);

 
 
  • 1
  • 2

但是不是我们分析的重点,所以不看,直接进入下一步,触发所以已注册的Bean工厂后置处理器的回调,首先看看什么是Bean工厂后置处理器

@FunctionalInterface
public interface BeanFactoryPostProcessor {
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

  • 1
  • 2
  • 3
  • 4
  • 5

这个就是Bean工厂后置处理器的接口,实现了这个接口的实现类就是Bean工厂的后置处理器,实现类实现的方法postProcessBeanFactory,会在BeanFactory创建完毕并且BeanDefinition加载后,的得到回调。运行我们去对BeanFactory做一些操作,例如继续往里面添加机构BeanDefinition,或者修改里面的信息

回到refresh方法中,现在refresh方法中走到这一步

// 调用上下文中注册为bean的工厂处理器。
invokeBeanFactoryPostProcessors(beanFactory);

 
 
  • 1
  • 2

org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors

	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		/**
		 * 这里主要工作是:
		 * 执行所有的注册到Spring中的BeanFactoryPostProcessor的实现类的postProcessBeanFactory方法
		 *
		 * 但是会在此之前先处理:
		 * 调用容器中所有实现了BeanDefinitionRegistryPostProcessor的实现类的postProcessBeanDefinitionRegistry方法
		 * 而BeanDefinitionRegistryPostProcessor又继承了BeanFactoryPostProcessor
		 * 其中Spring-Mybatis就是利用这个方法进行Mapper的扫描和注册成BeanDefinition
		 */
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
	<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List<org.springframework.beans.factory.config.BeanFactoryPostProcessor>)

	public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
	<span class="token comment">// 首先执行 BeanDefinitionRegistryPostProcessors , 如果有的话.</span>
	Set<span class="token generics function"><span class="token punctuation">&lt;</span>String<span class="token punctuation">&gt;</span></span> processedBeans <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HashSet</span><span class="token operator">&lt;</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token keyword">if</span> <span class="token punctuation">(</span>beanFactory <span class="token keyword">instanceof</span> <span class="token class-name">BeanDefinitionRegistry</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
		BeanDefinitionRegistry registry <span class="token operator">=</span> <span class="token punctuation">(</span>BeanDefinitionRegistry<span class="token punctuation">)</span> beanFactory<span class="token punctuation">;</span>
		List<span class="token generics function"><span class="token punctuation">&lt;</span>BeanFactoryPostProcessor<span class="token punctuation">&gt;</span></span> regularPostProcessors <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ArrayList</span><span class="token operator">&lt;</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		List<span class="token generics function"><span class="token punctuation">&lt;</span>BeanDefinitionRegistryPostProcessor<span class="token punctuation">&gt;</span></span> registryProcessors <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ArrayList</span><span class="token operator">&lt;</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token comment">/**
		 * 循环遍历所有的BeanFactoryPostProcessor,
		 * 发现是BeanDefinitionRegistryPostProcessor类型,
		 * 则调用他的postProcessBeanDefinitionRegistry.
		 * 把BeanDefinitionRegistry对象传入进去,
		 * 所以这里允许BeanDefinitionRegistryPostProcessor可以继续像容器注册一些额外的BeanDefinition
		 * 例如Spring-Mybatis中注册了所有扫描到的Mapper
		 */</span>
		<span class="token keyword">for</span> <span class="token punctuation">(</span>BeanFactoryPostProcessor postProcessor <span class="token operator">:</span> beanFactoryPostProcessors<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			<span class="token keyword">if</span> <span class="token punctuation">(</span>postProcessor <span class="token keyword">instanceof</span> <span class="token class-name">BeanDefinitionRegistryPostProcessor</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
				BeanDefinitionRegistryPostProcessor registryProcessor <span class="token operator">=</span>
						<span class="token punctuation">(</span>BeanDefinitionRegistryPostProcessor<span class="token punctuation">)</span> postProcessor<span class="token punctuation">;</span>
				registryProcessor<span class="token punctuation">.</span><span class="token function">postProcessBeanDefinitionRegistry</span><span class="token punctuation">(</span>registry<span class="token punctuation">)</span><span class="token punctuation">;</span>
				registryProcessors<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>registryProcessor<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span>
			<span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
				regularPostProcessors<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>postProcessor<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span>
		<span class="token punctuation">}</span>

		<span class="token comment">// Do not initialize FactoryBeans here: We need to leave all regular beans</span>
		<span class="token comment">// uninitialized to let the bean factory post-processors apply to them!</span>
		<span class="token comment">// Separate between BeanDefinitionRegistryPostProcessors that implement</span>
		<span class="token comment">// PriorityOrdered, Ordered, and the rest.</span>
		List<span class="token generics function"><span class="token punctuation">&lt;</span>BeanDefinitionRegistryPostProcessor<span class="token punctuation">&gt;</span></span> currentRegistryProcessors <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ArrayList</span><span class="token operator">&lt;</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

		<span class="token comment">// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.</span>
		String<span class="token punctuation">[</span><span class="token punctuation">]</span> postProcessorNames <span class="token operator">=</span>
				beanFactory<span class="token punctuation">.</span><span class="token function">getBeanNamesForType</span><span class="token punctuation">(</span>BeanDefinitionRegistryPostProcessor<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">for</span> <span class="token punctuation">(</span>String ppName <span class="token operator">:</span> postProcessorNames<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			<span class="token keyword">if</span> <span class="token punctuation">(</span>beanFactory<span class="token punctuation">.</span><span class="token function">isTypeMatch</span><span class="token punctuation">(</span>ppName<span class="token punctuation">,</span> PriorityOrdered<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
				currentRegistryProcessors<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>beanFactory<span class="token punctuation">.</span><span class="token function">getBean</span><span class="token punctuation">(</span>ppName<span class="token punctuation">,</span> BeanDefinitionRegistryPostProcessor<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
				processedBeans<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>ppName<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span>
		<span class="token punctuation">}</span>
		<span class="token function">sortPostProcessors</span><span class="token punctuation">(</span>currentRegistryProcessors<span class="token punctuation">,</span> beanFactory<span class="token punctuation">)</span><span class="token punctuation">;</span>
		registryProcessors<span class="token punctuation">.</span><span class="token function">addAll</span><span class="token punctuation">(</span>currentRegistryProcessors<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token comment">/* 通过BeanFactoryPostProcesser完成注解版BeanDefinition的解析注册 */</span>
		<span class="token function">invokeBeanDefinitionRegistryPostProcessors</span><span class="token punctuation">(</span>currentRegistryProcessors<span class="token punctuation">,</span> registry<span class="token punctuation">,</span> beanFactory<span class="token punctuation">.</span><span class="token function">getApplicationStartup</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		currentRegistryProcessors<span class="token punctuation">.</span><span class="token function">clear</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

		<span class="token comment">// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.</span>
		postProcessorNames <span class="token operator">=</span> beanFactory<span class="token punctuation">.</span><span class="token function">getBeanNamesForType</span><span class="token punctuation">(</span>BeanDefinitionRegistryPostProcessor<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">for</span> <span class="token punctuation">(</span>String ppName <span class="token operator">:</span> postProcessorNames<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>processedBeans<span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span>ppName<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> beanFactory<span class="token punctuation">.</span><span class="token function">isTypeMatch</span><span class="token punctuation">(</span>ppName<span class="token punctuation">,</span> Ordered<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
				currentRegistryProcessors<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>beanFactory<span class="token punctuation">.</span><span class="token function">getBean</span><span class="token punctuation">(</span>ppName<span class="token punctuation">,</span> BeanDefinitionRegistryPostProcessor<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
				processedBeans<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>ppName<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span>
		<span class="token punctuation">}</span>
		<span class="token function">sortPostProcessors</span><span class="token punctuation">(</span>currentRegistryProcessors<span class="token punctuation">,</span> beanFactory<span class="token punctuation">)</span><span class="token punctuation">;</span>
		registryProcessors<span class="token punctuation">.</span><span class="token function">addAll</span><span class="token punctuation">(</span>currentRegistryProcessors<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token function">invokeBeanDefinitionRegistryPostProcessors</span><span class="token punctuation">(</span>currentRegistryProcessors<span class="token punctuation">,</span> registry<span class="token punctuation">,</span> beanFactory<span class="token punctuation">.</span><span class="token function">getApplicationStartup</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		currentRegistryProcessors<span class="token punctuation">.</span><span class="token function">clear</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

		<span class="token comment">// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.</span>
		<span class="token keyword">boolean</span> reiterate <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
		<span class="token keyword">while</span> <span class="token punctuation">(</span>reiterate<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			reiterate <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
			postProcessorNames <span class="token operator">=</span> beanFactory<span class="token punctuation">.</span><span class="token function">getBeanNamesForType</span><span class="token punctuation">(</span>BeanDefinitionRegistryPostProcessor<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token keyword">for</span> <span class="token punctuation">(</span>String ppName <span class="token operator">:</span> postProcessorNames<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
				<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>processedBeans<span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span>ppName<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
					currentRegistryProcessors<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>beanFactory<span class="token punctuation">.</span><span class="token function">getBean</span><span class="token punctuation">(</span>ppName<span class="token punctuation">,</span> BeanDefinitionRegistryPostProcessor<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
					processedBeans<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>ppName<span class="token punctuation">)</span><span class="token punctuation">;</span>
					reiterate <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
				<span class="token punctuation">}</span>
			<span class="token punctuation">}</span>
			<span class="token function">sortPostProcessors</span><span class="token punctuation">(</span>currentRegistryProcessors<span class="token punctuation">,</span> beanFactory<span class="token punctuation">)</span><span class="token punctuation">;</span>
			registryProcessors<span class="token punctuation">.</span><span class="token function">addAll</span><span class="token punctuation">(</span>currentRegistryProcessors<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token function">invokeBeanDefinitionRegistryPostProcessors</span><span class="token punctuation">(</span>currentRegistryProcessors<span class="token punctuation">,</span> registry<span class="token punctuation">,</span> beanFactory<span class="token punctuation">.</span><span class="token function">getApplicationStartup</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			currentRegistryProcessors<span class="token punctuation">.</span><span class="token function">clear</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>

		<span class="token comment">// 现在, 执行所有工厂后置处理器的 postProcessBeanFactory 回调方法</span>
		<span class="token comment">/* 再次执行BeanFactoryPostProcesser完成cglib代理 */</span>
		<span class="token function">invokeBeanFactoryPostProcessors</span><span class="token punctuation">(</span>registryProcessors<span class="token punctuation">,</span> beanFactory<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token function">invokeBeanFactoryPostProcessors</span><span class="token punctuation">(</span>regularPostProcessors<span class="token punctuation">,</span> beanFactory<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
		<span class="token comment">// Invoke factory processors registered with the context instance.</span>
		<span class="token function">invokeBeanFactoryPostProcessors</span><span class="token punctuation">(</span>beanFactoryPostProcessors<span class="token punctuation">,</span> beanFactory<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token comment">// Do not initialize FactoryBeans here: We need to leave all regular beans</span>
	<span class="token comment">// uninitialized to let the bean factory post-processors apply to them!</span>
	String<span class="token punctuation">[</span><span class="token punctuation">]</span> postProcessorNames <span class="token operator">=</span>
			beanFactory<span class="token punctuation">.</span><span class="token function">getBeanNamesForType</span><span class="token punctuation">(</span>BeanFactoryPostProcessor<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token comment">// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,</span>
	<span class="token comment">// Ordered, and the rest.</span>
	List<span class="token generics function"><span class="token punctuation">&lt;</span>BeanFactoryPostProcessor<span class="token punctuation">&gt;</span></span> priorityOrderedPostProcessors <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ArrayList</span><span class="token operator">&lt;</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	List<span class="token generics function"><span class="token punctuation">&lt;</span>String<span class="token punctuation">&gt;</span></span> orderedPostProcessorNames <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ArrayList</span><span class="token operator">&lt;</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	List<span class="token generics function"><span class="token punctuation">&lt;</span>String<span class="token punctuation">&gt;</span></span> nonOrderedPostProcessorNames <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ArrayList</span><span class="token operator">&lt;</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token keyword">for</span> <span class="token punctuation">(</span>String ppName <span class="token operator">:</span> postProcessorNames<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>processedBeans<span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span>ppName<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			<span class="token comment">// skip - already processed in first phase above</span>
		<span class="token punctuation">}</span>
		<span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>beanFactory<span class="token punctuation">.</span><span class="token function">isTypeMatch</span><span class="token punctuation">(</span>ppName<span class="token punctuation">,</span> PriorityOrdered<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			priorityOrderedPostProcessors<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>beanFactory<span class="token punctuation">.</span><span class="token function">getBean</span><span class="token punctuation">(</span>ppName<span class="token punctuation">,</span> BeanFactoryPostProcessor<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
		<span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>beanFactory<span class="token punctuation">.</span><span class="token function">isTypeMatch</span><span class="token punctuation">(</span>ppName<span class="token punctuation">,</span> Ordered<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			orderedPostProcessorNames<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>ppName<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
		<span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
			nonOrderedPostProcessorNames<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>ppName<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span>

	<span class="token comment">// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.</span>
	<span class="token function">sortPostProcessors</span><span class="token punctuation">(</span>priorityOrderedPostProcessors<span class="token punctuation">,</span> beanFactory<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token function">invokeBeanFactoryPostProcessors</span><span class="token punctuation">(</span>priorityOrderedPostProcessors<span class="token punctuation">,</span> beanFactory<span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token comment">// Next, invoke the BeanFactoryPostProcessors that implement Ordered.</span>
	List<span class="token generics function"><span class="token punctuation">&lt;</span>BeanFactoryPostProcessor<span class="token punctuation">&gt;</span></span> orderedPostProcessors <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ArrayList</span><span class="token operator">&lt;</span><span class="token operator">&gt;</span><span class="token punctuation">(</span>orderedPostProcessorNames<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token keyword">for</span> <span class="token punctuation">(</span>String postProcessorName <span class="token operator">:</span> orderedPostProcessorNames<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
		orderedPostProcessors<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>beanFactory<span class="token punctuation">.</span><span class="token function">getBean</span><span class="token punctuation">(</span>postProcessorName<span class="token punctuation">,</span> BeanFactoryPostProcessor<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token function">sortPostProcessors</span><span class="token punctuation">(</span>orderedPostProcessors<span class="token punctuation">,</span> beanFactory<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token function">invokeBeanFactoryPostProcessors</span><span class="token punctuation">(</span>orderedPostProcessors<span class="token punctuation">,</span> beanFactory<span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token comment">// Finally, invoke all other BeanFactoryPostProcessors.</span>
	List<span class="token generics function"><span class="token punctuation">&lt;</span>BeanFactoryPostProcessor<span class="token punctuation">&gt;</span></span> nonOrderedPostProcessors <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ArrayList</span><span class="token operator">&lt;</span><span class="token operator">&gt;</span><span class="token punctuation">(</span>nonOrderedPostProcessorNames<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token keyword">for</span> <span class="token punctuation">(</span>String postProcessorName <span class="token operator">:</span> nonOrderedPostProcessorNames<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
		nonOrderedPostProcessors<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>beanFactory<span class="token punctuation">.</span><span class="token function">getBean</span><span class="token punctuation">(</span>postProcessorName<span class="token punctuation">,</span> BeanFactoryPostProcessor<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token function">invokeBeanFactoryPostProcessors</span><span class="token punctuation">(</span>nonOrderedPostProcessors<span class="token punctuation">,</span> beanFactory<span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token comment">// Clear cached merged bean definitions since the post-processors might have</span>
	<span class="token comment">// modified the original metadata, e.g. replacing placeholders in values...</span>
	beanFactory<span class="token punctuation">.</span><span class="token function">clearMetadataCache</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141

这里方法很长步骤很多,首先是先触发BeanDefinitionRegistryPostProcessors的子类的回调,执行他的则调用他的postProcessBeanDefinitionRegistry方法,BeanDefinitionRegistryPostProcessors也实现了BeanFactoryPostProcessor 接口,所以也是特殊的Bean工厂后置处理器。

然后注解版的Bean这样在这里加载并注册

最后就会进行BeanFactoryPostProcesser的回调

实例化并初始化所有的Bean

现在Bean工厂的后置处理器回调已经完成,回到refresh方法中。

接下啦是注册 BeanPostProcessor 的实现类,也就是Bean后置处理,Bean工厂后置处理器是作用域BeanFactory的,而Bean后置处理器是作用于Bean的。

// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
registerBeanPostProcessors(beanFactory);

 
 
  • 1
  • 2
  • 3
  • 4

这里就不展开了

然后是国际化

// 初始化当前 ApplicationContext 的 MessageSource,国际化
initMessageSource();

 
 
  • 1
  • 2

也不展开,然后是

// 初始化当前 ApplicationContext 的事件广播器
initApplicationEventMulticaster();

 
 
  • 1
  • 2

也不展开,然后是

// 从方法名就可以知道,典型的模板方法(钩子方法),
// 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
onRefresh();

 
 
  • 1
  • 2
  • 3

onRrefresh方法时留给子类的一个扩展点,例如在SpringBoot中,就是通过这个方法,完成Tomcat的手动启动,这里不展开

注册事件监听器

// 注册事件监听器,监听器需要实现 ApplicationListener 接口
registerListeners();

 
 
  • 1
  • 2

下面进入重点方法,bean的实例化和初始化

// 实例化和初始化所有的bean
finishBeanFactoryInitialization(beanFactory);

 
 
  • 1
  • 2

org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization

	protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// 首先,初始化名字为 conversionService 的 Bean
		// 初始化的动作包装在 beanFactory.getBean(...) 中
		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));
		}
	<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>

	<span class="token comment">// 先初始化 LoadTimeWeaverAware 类型的 Bean</span>
	<span class="token comment">// 一般用于织入第三方模块,在 class 文件载入 JVM 的时候动态织入,</span>
	String<span class="token punctuation">[</span><span class="token punctuation">]</span> weaverAwareNames <span class="token operator">=</span> beanFactory<span class="token punctuation">.</span><span class="token function">getBeanNamesForType</span><span class="token punctuation">(</span>LoadTimeWeaverAware<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token keyword">for</span> <span class="token punctuation">(</span>String weaverAwareName <span class="token operator">:</span> weaverAwareNames<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
		<span class="token function">getBean</span><span class="token punctuation">(</span>weaverAwareName<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>

	<span class="token comment">// 开始初始化</span>
	beanFactory<span class="token punctuation">.</span><span class="token function">preInstantiateSingletons</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

我们直接看最后一步 beanFactory.preInstantiateSingletons();

org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons

	@Override
	public void preInstantiateSingletons() throws BeansException {
		...
		/* 获取先前扫描注册BeanDefinition是保存的beanNames */
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
	<span class="token comment">// 触发所有的非懒加载的 singleton beans 的初始化操作</span>
	<span class="token keyword">for</span> <span class="token punctuation">(</span>String beanName <span class="token operator">:</span> beanNames<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
		<span class="token comment">// 合并父 Bean 中的配置,注意 &lt;bean id="" class="" parent="" /&gt; 中的 parent</span>
		RootBeanDefinition bd <span class="token operator">=</span> <span class="token function">getMergedLocalBeanDefinition</span><span class="token punctuation">(</span>beanName<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token comment">// 非抽象、非懒加载的 singletons。如果配置了 'abstract = true',那是不需要初始化的</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>bd<span class="token punctuation">.</span><span class="token function">isAbstract</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> bd<span class="token punctuation">.</span><span class="token function">isSingleton</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span>bd<span class="token punctuation">.</span><span class="token function">isLazyInit</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			<span class="token comment">// 处理 FactoryBean</span>
			<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isFactoryBean</span><span class="token punctuation">(</span>beanName<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
				<span class="token comment">// FactoryBean 的话,在 beanName 前面加上 ‘&amp;’ 符号。再调用 getBean,getBean</span>
				Object bean <span class="token operator">=</span> <span class="token function">getBean</span><span class="token punctuation">(</span>FACTORY_BEAN_PREFIX <span class="token operator">+</span> beanName<span class="token punctuation">)</span><span class="token punctuation">;</span>
				<span class="token keyword">if</span> <span class="token punctuation">(</span>bean <span class="token keyword">instanceof</span> <span class="token class-name">FactoryBean</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
					FactoryBean<span class="token operator">&lt;</span><span class="token operator">?</span><span class="token operator">&gt;</span> factory <span class="token operator">=</span> <span class="token punctuation">(</span>FactoryBean<span class="token operator">&lt;</span><span class="token operator">?</span><span class="token operator">&gt;</span><span class="token punctuation">)</span> bean<span class="token punctuation">;</span>
					<span class="token keyword">boolean</span> isEagerInit<span class="token punctuation">;</span>
					<span class="token keyword">if</span> <span class="token punctuation">(</span>System<span class="token punctuation">.</span><span class="token function">getSecurityManager</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">!=</span> null <span class="token operator">&amp;&amp;</span> factory <span class="token keyword">instanceof</span> <span class="token class-name">SmartFactoryBean</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
						isEagerInit <span class="token operator">=</span> AccessController<span class="token punctuation">.</span><span class="token function">doPrivileged</span><span class="token punctuation">(</span>
								<span class="token punctuation">(</span>PrivilegedAction<span class="token generics function"><span class="token punctuation">&lt;</span>Boolean<span class="token punctuation">&gt;</span></span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>SmartFactoryBean<span class="token operator">&lt;</span><span class="token operator">?</span><span class="token operator">&gt;</span><span class="token punctuation">)</span> factory<span class="token punctuation">)</span><span class="token operator">:</span><span class="token operator">:</span>isEagerInit<span class="token punctuation">,</span>
								<span class="token function">getAccessControlContext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
					<span class="token punctuation">}</span>
					<span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
						isEagerInit <span class="token operator">=</span> <span class="token punctuation">(</span>factory <span class="token keyword">instanceof</span> <span class="token class-name">SmartFactoryBean</span> <span class="token operator">&amp;&amp;</span>
								<span class="token punctuation">(</span><span class="token punctuation">(</span>SmartFactoryBean<span class="token operator">&lt;</span><span class="token operator">?</span><span class="token operator">&gt;</span><span class="token punctuation">)</span> factory<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">isEagerInit</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
					<span class="token punctuation">}</span>
					<span class="token keyword">if</span> <span class="token punctuation">(</span>isEagerInit<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
						<span class="token function">getBean</span><span class="token punctuation">(</span>beanName<span class="token punctuation">)</span><span class="token punctuation">;</span>
					<span class="token punctuation">}</span>
				<span class="token punctuation">}</span>
			<span class="token punctuation">}</span>
			<span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
				<span class="token comment">// 对于普通的 Bean,只要调用 getBean(beanName) 这个方法就可以进行初始化了</span>
				<span class="token function">getBean</span><span class="token punctuation">(</span>beanName<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span>

	<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

这里首先从DefaultListableBeanFactory的成员变量beanDefinitionNames中获取所有的beanName,这是之前加载BeanDefinition时注册进去的。然后遍历所有的beanName,调用getBean方法。

org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)

	@Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}

 
 
  • 1
  • 2
  • 3
  • 4

org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

	protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
	<span class="token comment">// 获取一个 “正统的” beanName,处理两种情况,一个是前面说的 FactoryBean(前面带 ‘&amp;’),</span>
	<span class="token comment">// 一个是别名问题,因为这个方法是 getBean,获取 Bean 用的,你要是传一个别名进来,是完全可以的</span>
	String beanName <span class="token operator">=</span> <span class="token function">transformedBeanName</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token comment">// 注意跟着这个,这个是返回值</span>
	Object bean<span class="token punctuation">;</span>

	<span class="token comment">/**
	 * 尝试从BeanFactory的三个缓存池中获取该bean
	 * 获取得到则返回,不走下面的创建初始化方法。
	 * 此处作用:
	 * 1.给已经创建过的bean,再调getBean是获取该bean
	 * 2.处理循环依赖时返回该bean的半成品(已创建未初始化)
	 */</span>
	Object sharedInstance <span class="token operator">=</span> <span class="token function">getSingleton</span><span class="token punctuation">(</span>beanName<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token keyword">if</span> <span class="token punctuation">(</span>sharedInstance <span class="token operator">!=</span> null <span class="token operator">&amp;&amp;</span> args <span class="token operator">==</span> null<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>logger<span class="token punctuation">.</span><span class="token function">isTraceEnabled</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
		<span class="token punctuation">}</span>
		<span class="token comment">// 下面这个方法:如果是普通 Bean 的话,直接返回 sharedInstance,</span>
		<span class="token comment">// 如果是 FactoryBean 的话,返回它创建的那个实例对象</span>
		bean <span class="token operator">=</span> <span class="token function">getObjectForBeanInstance</span><span class="token punctuation">(</span>sharedInstance<span class="token punctuation">,</span> name<span class="token punctuation">,</span> beanName<span class="token punctuation">,</span> null<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token comment">/*第一次getBean,就会进入else分支*/</span>
	<span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
		<span class="token comment">// 当前线程已经创建过了此 beanName 的 prototype 类型的 bean,那么抛异常</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isPrototypeCurrentlyInCreation</span><span class="token punctuation">(</span>beanName<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">BeanCurrentlyInCreationException</span><span class="token punctuation">(</span>beanName<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>

		<span class="token comment">// 检查一下这个 BeanDefinition 在容器中是否存在</span>
		BeanFactory parentBeanFactory <span class="token operator">=</span> <span class="token function">getParentBeanFactory</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token comment">/* 父容器不为空,且当前容器不存在此BeanDefinition */</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>parentBeanFactory <span class="token operator">!=</span> null <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span><span class="token function">containsBeanDefinition</span><span class="token punctuation">(</span>beanName<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			<span class="token comment">// 如果当前容器不存在这个 Binition,试试父容器中有没有eanDef</span>
			String nameToLookup <span class="token operator">=</span> <span class="token function">originalBeanName</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token keyword">if</span> <span class="token punctuation">(</span>parentBeanFactory <span class="token keyword">instanceof</span> <span class="token class-name">AbstractBeanFactory</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
				<span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>AbstractBeanFactory<span class="token punctuation">)</span> parentBeanFactory<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">doGetBean</span><span class="token punctuation">(</span>
						nameToLookup<span class="token punctuation">,</span> requiredType<span class="token punctuation">,</span> args<span class="token punctuation">,</span> typeCheckOnly<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span>
			<span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>args <span class="token operator">!=</span> null<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
				<span class="token comment">// Delegation to parent with explicit args.</span>
				<span class="token keyword">return</span> <span class="token punctuation">(</span>T<span class="token punctuation">)</span> parentBeanFactory<span class="token punctuation">.</span><span class="token function">getBean</span><span class="token punctuation">(</span>nameToLookup<span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span>
			<span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>requiredType <span class="token operator">!=</span> null<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
				<span class="token comment">// No args -&gt; delegate to standard getBean method.</span>
				<span class="token keyword">return</span> parentBeanFactory<span class="token punctuation">.</span><span class="token function">getBean</span><span class="token punctuation">(</span>nameToLookup<span class="token punctuation">,</span> requiredType<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span>
			<span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
				<span class="token keyword">return</span> <span class="token punctuation">(</span>T<span class="token punctuation">)</span> parentBeanFactory<span class="token punctuation">.</span><span class="token function">getBean</span><span class="token punctuation">(</span>nameToLookup<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span>
		<span class="token punctuation">}</span>

		<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>typeCheckOnly<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			<span class="token function">markBeanAsCreated</span><span class="token punctuation">(</span>beanName<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>

		<span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span>
			StartupStep beanCreation <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>applicationStartup<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token string">"spring.beans.instantiate"</span><span class="token punctuation">)</span>
					<span class="token punctuation">.</span><span class="token function">tag</span><span class="token punctuation">(</span><span class="token string">"beanName"</span><span class="token punctuation">,</span> name<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token keyword">if</span> <span class="token punctuation">(</span>requiredType <span class="token operator">!=</span> null<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
				beanCreation<span class="token punctuation">.</span><span class="token function">tag</span><span class="token punctuation">(</span><span class="token string">"beanType"</span><span class="token punctuation">,</span> requiredType<span class="token operator">:</span><span class="token operator">:</span>toString<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span>
			<span class="token comment">/* 准备创建bean,先获取BeanDefinition */</span>
			RootBeanDefinition mbd <span class="token operator">=</span> <span class="token function">getMergedLocalBeanDefinition</span><span class="token punctuation">(</span>beanName<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token function">checkMergedBeanDefinition</span><span class="token punctuation">(</span>mbd<span class="token punctuation">,</span> beanName<span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>

			<span class="token comment">// 先初始化依赖的所有 Bean</span>
			<span class="token comment">// 注意,这里的依赖指的是 depends-on 中定义的依赖</span>
			String<span class="token punctuation">[</span><span class="token punctuation">]</span> dependsOn <span class="token operator">=</span> mbd<span class="token punctuation">.</span><span class="token function">getDependsOn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token keyword">if</span> <span class="token punctuation">(</span>dependsOn <span class="token operator">!=</span> null<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
				<span class="token keyword">for</span> <span class="token punctuation">(</span>String dep <span class="token operator">:</span> dependsOn<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
					<span class="token comment">// 检查是不是有循环依赖,这里的循环依赖和我们前面说的循环依赖又不一样,这里肯定是不允许出现的</span>
					<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isDependent</span><span class="token punctuation">(</span>beanName<span class="token punctuation">,</span> dep<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
						<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">BeanCreationException</span><span class="token punctuation">(</span>mbd<span class="token punctuation">.</span><span class="token function">getResourceDescription</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> beanName<span class="token punctuation">,</span>
								<span class="token string">"Circular depends-on relationship between '"</span> <span class="token operator">+</span> beanName <span class="token operator">+</span> <span class="token string">"' and '"</span> <span class="token operator">+</span> dep <span class="token operator">+</span> <span class="token string">"'"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
					<span class="token punctuation">}</span>
					<span class="token comment">// 注册一下依赖关系</span>
					<span class="token function">registerDependentBean</span><span class="token punctuation">(</span>dep<span class="token punctuation">,</span> beanName<span class="token punctuation">)</span><span class="token punctuation">;</span>
					<span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span>
						<span class="token comment">// 先初始化被依赖项</span>
						<span class="token function">getBean</span><span class="token punctuation">(</span>dep<span class="token punctuation">)</span><span class="token punctuation">;</span>
					<span class="token punctuation">}</span>
					<span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">NoSuchBeanDefinitionException</span> ex<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
						<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">BeanCreationException</span><span class="token punctuation">(</span>mbd<span class="token punctuation">.</span><span class="token function">getResourceDescription</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> beanName<span class="token punctuation">,</span>
								<span class="token string">"'"</span> <span class="token operator">+</span> beanName <span class="token operator">+</span> <span class="token string">"' depends on missing bean '"</span> <span class="token operator">+</span> dep <span class="token operator">+</span> <span class="token string">"'"</span><span class="token punctuation">,</span> ex<span class="token punctuation">)</span><span class="token punctuation">;</span>
					<span class="token punctuation">}</span>
				<span class="token punctuation">}</span>
			<span class="token punctuation">}</span>

			<span class="token comment">// singleton 实例的创建分支</span>
			<span class="token keyword">if</span> <span class="token punctuation">(</span>mbd<span class="token punctuation">.</span><span class="token function">isSingleton</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
				<span class="token comment">/* getSingleton会在里面调用此匿名内部类ObjectFactory创建Bean */</span>
				sharedInstance <span class="token operator">=</span> <span class="token function">getSingleton</span><span class="token punctuation">(</span>beanName<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">&gt;</span> <span class="token punctuation">{<!-- --></span>
					<span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span>
						<span class="token comment">/* 真正创建Bean的方法 */</span>
						<span class="token keyword">return</span> <span class="token function">createBean</span><span class="token punctuation">(</span>beanName<span class="token punctuation">,</span> mbd<span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>
					<span class="token punctuation">}</span>
					<span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">BeansException</span> ex<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
						<span class="token function">destroySingleton</span><span class="token punctuation">(</span>beanName<span class="token punctuation">)</span><span class="token punctuation">;</span>
						<span class="token keyword">throw</span> ex<span class="token punctuation">;</span>
					<span class="token punctuation">}</span>
				<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
				<span class="token comment">/**
				 * 获取真正的返回值:
				 * 如果是putongbean,就是此sharedInstance对象
				 * 如果是FactoryBean:
				 * 	1.beanName前带&amp;,则返回该FactoryBean
				 * 	2.否则返回给FactoryBean的getObject返回的Bean
				 */</span>
				bean <span class="token operator">=</span> <span class="token function">getObjectForBeanInstance</span><span class="token punctuation">(</span>sharedInstance<span class="token punctuation">,</span> name<span class="token punctuation">,</span> beanName<span class="token punctuation">,</span> mbd<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span>

			<span class="token comment">// prototype 实例的创建分支</span>
			<span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>mbd<span class="token punctuation">.</span><span class="token function">isPrototype</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
				<span class="token comment">// It's a prototype -&gt; create a new instance.</span>
				Object prototypeInstance <span class="token operator">=</span> null<span class="token punctuation">;</span>
				<span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span>
					<span class="token function">beforePrototypeCreation</span><span class="token punctuation">(</span>beanName<span class="token punctuation">)</span><span class="token punctuation">;</span>
					prototypeInstance <span class="token operator">=</span> <span class="token function">createBean</span><span class="token punctuation">(</span>beanName<span class="token punctuation">,</span> mbd<span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>
				<span class="token punctuation">}</span>
				<span class="token keyword">finally</span> <span class="token punctuation">{<!-- --></span>
					<span class="token function">afterPrototypeCreation</span><span class="token punctuation">(</span>beanName<span class="token punctuation">)</span><span class="token punctuation">;</span>
				<span class="token punctuation">}</span>
				bean <span class="token operator">=</span> <span class="token function">getObjectForBeanInstance</span><span class="token punctuation">(</span>prototypeInstance<span class="token punctuation">,</span> name<span class="token punctuation">,</span> beanName<span class="token punctuation">,</span> mbd<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span>

			<span class="token comment">// 如果不是 singleton 和 prototype 的话,需要委托给相应的实现类来处理</span>
			<span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
				String scopeName <span class="token operator">=</span> mbd<span class="token punctuation">.</span><span class="token function">getScope</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
				<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>StringUtils<span class="token punctuation">.</span><span class="token function">hasLength</span><span class="token punctuation">(</span>scopeName<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
					<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalStateException</span><span class="token punctuation">(</span><span class="token string">"No scope name defined for bean ´"</span> <span class="token operator">+</span> beanName <span class="token operator">+</span> <span class="token string">"'"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
				<span class="token punctuation">}</span>
				Scope scope <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>scopes<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>scopeName<span class="token punctuation">)</span><span class="token punctuation">;</span>
				<span class="token keyword">if</span> <span class="token punctuation">(</span>scope <span class="token operator">==</span> null<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
					<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalStateException</span><span class="token punctuation">(</span><span class="token string">"No Scope registered for scope name '"</span> <span class="token operator">+</span> scopeName <span class="token operator">+</span> <span class="token string">"'"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
				<span class="token punctuation">}</span>
				<span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span>
					Object scopedInstance <span class="token operator">=</span> scope<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>beanName<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">&gt;</span> <span class="token punctuation">{<!-- --></span>
						<span class="token function">beforePrototypeCreation</span><span class="token punctuation">(</span>beanName<span class="token punctuation">)</span><span class="token punctuation">;</span>
						<span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span>
							<span class="token keyword">return</span> <span class="token function">createBean</span><span class="token punctuation">(</span>beanName<span class="token punctuation">,</span> mbd<span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>
						<span class="token punctuation">}</span>
						<span class="token keyword">finally</span> <span class="token punctuation">{<!-- --></span>
							<span class="token function">afterPrototypeCreation</span><span class="token punctuation">(</span>beanName<span class="token punctuation">)</span><span class="token punctuation">;</span>
						<span class="token punctuation">}</span>
					<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
					bean <span class="token operator">=</span> <span class="token function">getObjectForBeanInstance</span><span class="token punctuation">(</span>scopedInstance<span class="token punctuation">,</span> name<span class="token punctuation">,</span> beanName<span class="token punctuation">,</span> mbd<span class="token punctuation">)</span><span class="token punctuation">;</span>
				<span class="token punctuation">}</span>
				<span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">IllegalStateException</span> ex<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
					<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">ScopeNotActiveException</span><span class="token punctuation">(</span>beanName<span class="token punctuation">,</span> scopeName<span class="token punctuation">,</span> ex<span class="token punctuation">)</span><span class="token punctuation">;</span>
				<span class="token punctuation">}</span>
			<span class="token punctuation">}</span>
			beanCreation<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
		<span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">BeansException</span> ex<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			<span class="token function">cleanupAfterBeanCreationFailure</span><span class="token punctuation">(</span>beanName<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token keyword">throw</span> ex<span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span>

	<span class="token comment">// 最后,检查一下类型对不对,不对的话就抛异常,对的话就返回了</span>
	<span class="token keyword">if</span> <span class="token punctuation">(</span>requiredType <span class="token operator">!=</span> null <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span>requiredType<span class="token punctuation">.</span><span class="token function">isInstance</span><span class="token punctuation">(</span>bean<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
		<span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span>
			T convertedBean <span class="token operator">=</span> <span class="token function">getTypeConverter</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">convertIfNecessary</span><span class="token punctuation">(</span>bean<span class="token punctuation">,</span> requiredType<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token keyword">if</span> <span class="token punctuation">(</span>convertedBean <span class="token operator">==</span> null<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
				<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">BeanNotOfRequiredTypeException</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span> requiredType<span class="token punctuation">,</span> bean<span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span>
			<span class="token keyword">return</span> convertedBean<span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
		<span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">TypeMismatchException</span> ex<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
			<span class="token keyword">if</span> <span class="token punctuation">(</span>logger<span class="token punctuation">.</span><span class="token function">isTraceEnabled</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
				<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
			<span class="token punctuation">}</span>
			<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">BeanNotOfRequiredTypeException</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span> requiredType<span class="token punctuation">,</span> bean<span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span>
	<span class="token keyword">return</span> <span class="token punctuation">(</span>T<span class="token punctuation">)</span> bean<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184

这里方法很长,但是我们只要看一下几步就可以了

  1. Object sharedInstance = getSingleton(beanName); 先尝试从单例缓存池中获取
  2. sharedInstance = getSingleton(beanName, () -> {})singleton 实例的创建,getSingleton会在里面调用此匿名内部类ObjectFactory创建Bean
  3. createBean(beanName, mbd, args); 匿名内部类ObjectFactory的方法,真正创建Bean的方法

尝试从单例缓存池中获取

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String)

	@Override
	@Nullable
	public Object getSingleton(String beanName) {
		/* allowEarlyReference为true表示允许循环引用 */
		return getSingleton(beanName, true);
	}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)

	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		/*如果从一级缓存取到则直接返回,一般出现在获取已经完成的bean,或者单向引用 */
		Object singletonObject = this.singletonObjects.get(beanName);
		/*获取不到且当前beanName对应的Bean正在创建中(实例化后初始化前)*/
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				/*先从二级缓存中取*/
				singletonObject = this.earlySingletonObjects.get(beanName);
				/*二级完成取不到 && 允许循环引用*/
				if (singletonObject == null && allowEarlyReference) {
					/*从三级缓存中获取当前Bean对应的ObjectFactory */
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						/*获取到了,则调用getObject,获取当前正在创建中的对象*/
						singletonObject = singletonFactory.getObject();
						/*添加到二级缓存*/
						this.earlySingletonObjects.put(beanName, singletonObject);
						/*从三级缓存中删除,下次就直接从二级缓存中取了*/
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

这里第一次进来,肯定啥都取不到的,所以返回null

从缓存池取不到,则创建bean

创建bean前后的工作,进行标记

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)

	public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		synchronized (this.singletonObjects) {
			// 尝试从一级缓存中获取,但是第一次进来还是null
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				// 判断当前实例化的bean是否正在销毁的集合里面
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
					...
				}
				/**
				 * 当spring觉得可以着手来创建bean的时候首先便是调用beforeSingletonCreation(beanName)
				 * 判断当前正在实例化的bean是否存在正在创建的集合当中
				 * 当他需要正式创建bean的时候他会记录一下这个bean正在创建(add到一个set集合当中)
				 * 其实这个集合主要是为了循环依赖服务的
				 */
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					/**
					 * 调用ObjectFactory对象的getObject方法创建并初始化bean
					 * 就是外面那个lamda表达式
					 * 这一步走完,一个bean的创建和初始就完成了
					 */
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
					...
				}
				catch (BeanCreationException ex) {
					...
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					/*创建完成以后,把beanName从正在创建中的集合中remove掉 */
					
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值