Spring源码解析二 obtainFreshBeanFactory

我们接着上次的说,上次还剩下AnnotationConfigApplicationContex这个类的构造方法里调用的refresh();没有说,我们今天来看看这个重点方法:refresh();

目录

AbstractApplicationContext

refresh()方法解析

1、Refresh()方法之 prepareRefresh()

2、refresh()方法之obtainFreshBeanFactory()


 

AbstractApplicationContext

    refresh();   AbstractApplicationContext 类中。关系如下:

AnnotationConfigApplicationContext继承了GenericApplicationContext,而
GenericApplicationContext又继承了AbstractApplicationContext。所以说refresh()方法的执行流程是在父类AbstractApplicationContext的方法里。我们来进一步看看这个方法里都执行了什么。

refresh()方法解析

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			//1、 Prepare this context for refreshing.
			//准备刷新容器,刷新前的处理
			prepareRefresh();

			//2、 Tell the subclass to refresh the internal bean factory.
			//得到一个新的beanFactory
			//告诉子类刷新内部bean工厂。 用来保存 bean 的容器 相当于IOC容器
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			//3、 Prepare the bean factory for use in this context.
			//内容:准备bean工厂以供在此上下文中使用。一般在这里完成 BeanFactory 的创建,下一个方法是扩展
		
			prepareBeanFactory(beanFactory);

			try {
				//4、 Allows post-processing of the bean factory in context subclasses.
				// spring暂时没有接口实现,可能是后期spring会自己完善这个接口
				postProcessBeanFactory(beanFactory);

	//================以上是 BeanFactory 的创建及预准备工作(标准初始化)============================

				//5、 Invoke factory processors registered as beans in the context.
				// 调用上下文中注册为bean的工厂处理器。 执行BeanFactoryPostProcessors();
				// BeanFactory的后置处理器。在BeanFactory标准初始化后执行的,标准初始化就是前面的4步
				invokeBeanFactoryPostProcessors(beanFactory);

				//6、 Register bean processors that intercept bean creation.
				//注册bean后置处理器
				// 注册 BeanPostProcessor的实现类,注意看和BeanFactoryPostProcessor的区别
				// 此接口两个方法  1、postProcessBeforeInitialization 2、postProcessAfterInitialization
				// 两个方法分别在Bean初始化之前和初始化之后得到执行。注意:到这里bean还没初始化
				registerBeanPostProcessors(beanFactory);

				//7、 Initialize message source for this context.
				//做国际化功能:消息绑定,消息解析
				// 初始化当前applicationContext的MessageSource
				initMessageSource();

				//8、 Initialize event multicaster for this context. 初始化事件派发器
				initApplicationEventMulticaster();

				//9、 Initialize other special beans in specific context subclasses.
				//子类重写这个方法,在容器刷新的时候可以自定义逻辑
				onRefresh();

				//10、 Check for listener beans and register them.
				//   给容器中 将所有项目里面 ApplicationListener 注册进来,并且发布早期事件
				//注册事件监听器,监听器需要实现ApplicationListener接口
				registerListeners();

				//11、 Instantiate all remaining (non-lazy-init) singletons.
				// 初始化所有剩下的单实例 Bean
				//重点  重点 重点
				//初始化所有的 singleton beans
				// (lazy-init的除外)
				finishBeanFactoryInitialization(beanFactory);

				//12、 Last step: publish corresponding event.
				//最后一步:发布相应的事件。完成 beanFactory 的初始化创建工作;
				finishRefresh();
			}

			
		}
	}

可以看到refresh()方法里一共进行了十二的操作。我们一步一步的解析

 

1、Refresh()方法之 prepareRefresh()

        其实这个方法主要内容就是记录下容器启动时间,标记容器为活动状态,并执行初始化的属性源

protected void prepareRefresh() {
		// Switch to active. 切换到活动状态
		this.startupDate = System.currentTimeMillis();
		this.closed.set(false);
		this.active.set(true);

		if (logger.isDebugEnabled()) {
			if (logger.isTraceEnabled()) {
				logger.trace("Refreshing " + this);
			}
			else {
				logger.debug("Refreshing " + getDisplayName());
			}
		}

		// Initialize any placeholder property sources in the context environment.
		//在上下文环境中初始化任何占位符属性源。(由子容器去实现)
		// 目前没有子类去实现的,
		initPropertySources();

		// Validate that all properties marked as required are resolvable:
		// see ConfigurablePropertyResolver#setRequiredProperties
		// 检验属性的合法 等
		getEnvironment().validateRequiredProperties();

		// Store pre-refresh ApplicationListeners...
		if (this.earlyApplicationListeners == null) {
			this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
		}
		else {
			// Reset local application listeners to pre-refresh state.
			//将本地应用程序监听器重置为预刷新状态。
			this.applicationListeners.clear();
			this.applicationListeners.addAll(this.earlyApplicationListeners);
		}

		// Allow for the collection of early ApplicationEvents,
		// to be published once the multicaster is available...
		// 允许收集早期的ApplicationEvents,
		// 一旦多播机可用,就会发布…
		// 保存容器中一些早期的事件  					是ApplicationEvent类型
		// this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}

2、refresh()方法之obtainFreshBeanFactory()

 

刷新beanFactory 抽象方法,由子类实现。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {		
		refreshBeanFactory();
		return getBeanFactory();
	}

 

refreshBeanFactory()方法有两个实现类

 如果你用的是javaConfig技术,那么你应该看GenericApplicationContext这个实现,如果你用的是XML这种形式的,那么你应该看AbstractRefreshableApplicationContext。我们先看GenericApplicationContext这个类做了什么:

可以看到,在这个方法里,仅仅是设置了beanFactory的序列化ID。我们返回 

obtainFreshBeanFactory这个方法:

接着说:getBeanFactory()方法,点开这个方法,发现是一个抽象方法:

我们接着看GenericApplicationContext类的实现:

就是把已经创建好的beanFactory返回。至此注解版的这个方法就结束了,下面来说说以XML形式的方式。让我们重新看refreshBeanFactory()这个方法,抽象方法,需要看子类的实现:

 

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {

    ...

	protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;

    ...

}

而实际执行的方法是在AbstractRefreshableApplicationContext抽象类里执行的。

public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {

        ...

protected final void refreshBeanFactory() throws BeansException {
		// 如果ApplicationContext中已经加载过BeanFactory了,销毁虽有的Bean,关闭BeanFactory
		//注意:应用中BeanFactory本来就可以多个的,这里不是说应用全局是否有BeanFactory,
		// 而是当前ApplicationContext是否有BeanFactory
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			// 设置BeanFactory的两个配置属性:是否允许Bean覆盖,是否允许循环引用
			customizeBeanFactory(beanFactory);
			// 加载bean 到BeanFactory中
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

        ...
}

在这个方法里,先判断已经存在beanFactory,如果已经存在则进行销毁,而后创建一个新的BeanFactory,设置唯一ID,设置是否允许Bean覆盖与Bean的循环引用,加载bean到BeanFactory中。

我们先看 createBeanFactory()这个方法;

public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {

    ......

	protected DefaultListableBeanFactory createBeanFactory() {
		return new DefaultListableBeanFactory(getInternalParentBeanFactory());
	}


    ......
    
}

然后点开DefaultListableBeanFactory()这个创建Bean工厂的这个构造方法。

我们接着往里看:

在这个有参构造器里调用了无惨的构造方法:

我们看一下无惨构造方法里做了什么操作:

这里做了这样的操作:忽略了指定接口的自动装配,具体可以看注释。

 

 

再来看:customizeBeanFactory(beanFactory);beanFactory.setxxx()是一个布尔值,所以说,如果有人问你,Spring中的循环依赖能否关闭,你这就拿下面这段代码回答了。

protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
		if (this.allowBeanDefinitionOverriding != null) {
			// 是否允许bean定义覆盖
			beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
		}
		if (this.allowCircularReferences != null) {
			// 是否允许循环引用 A依赖B B依赖A 形成闭环
			beanFactory.setAllowCircularReferences(this.allowCircularReferences);
		}
	}

我们回到refreshBeanFactory()方法里,看loadBeanDefinitions(beanFactory);这个方法

这个抽象方法,有四个类进行了重写,我们分析AnnotationConfigWebApplicationContext,这个类

具体如下:

public class AnnotationConfigWebApplicationContext extends AbstractRefreshableWebApplicationContext
		implements AnnotationConfigRegistry {


        ...

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
		AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory);
		ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory);
		// 生成bean的名字生成器
		BeanNameGenerator beanNameGenerator = getBeanNameGenerator();
		if (beanNameGenerator != null) {
			reader.setBeanNameGenerator(beanNameGenerator);
			scanner.setBeanNameGenerator(beanNameGenerator);
			// 注册到容器里
			beanFactory.registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
		}
		// scoope的解析器
		ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver();
		if (scopeMetadataResolver != null) {
			reader.setScopeMetadataResolver(scopeMetadataResolver);
			scanner.setScopeMetadataResolver(scopeMetadataResolver);
		}

		if (!this.componentClasses.isEmpty()) {
			if (logger.isDebugEnabled()) {
				logger.debug("Registering component classes: [" +
						StringUtils.collectionToCommaDelimitedString(this.componentClasses) + "]");
			}
			// 若是指定的Bean,就交给reder中的doRegisterBean去解析每一个 Config Bean
			reader.register(ClassUtils.toClassArray(this.componentClasses));
		}

		// 扫描配置文件的Bean
		if (!this.basePackages.isEmpty()) {
			if (logger.isDebugEnabled()) {
				logger.debug("Scanning base packages: [" +
						StringUtils.collectionToCommaDelimitedString(this.basePackages) + "]");
			}
			// 这里很重要 spring提供的包扫描功能
			scanner.scan(StringUtils.toStringArray(this.basePackages));
		}

		
	}

    ...

}

1、先获取AnnotatedBeanDefinitionReader bean的读取器。如何获取这个读取器的呢?

   

直接new 了一个读取器,我们接着往里看。在这个方法里调用了

AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

熟悉不熟悉,我在上一篇文章中说过这个方法,这里就不在重复讲解了,清楚的可以看我上篇文章:https://mp-new.csdn.net/mp_blog/creation/editor/117809214

这里结束之后,我们的BeanFactory就不在孤单了,里面注册了几个特殊的Bean,这些特殊的Bean都非常重要,我们后续说,这里你要重点记住一个叫做:

internalConfigurationAnnotationProcessor的bean,这里先不多说,读者只需要记住有这么一个bean就可以了。

现在我们回到 AnnotationConfigWebApplicationContext-->loadBeanDefinitions 方法里:

public class AnnotationConfigWebApplicationContext extends AbstractRefreshableWebApplicationContext
		implements AnnotationConfigRegistry {


        ...

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
		AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory);
		ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory);
		// 生成bean的名字生成器
		BeanNameGenerator beanNameGenerator = getBeanNameGenerator();
		if (beanNameGenerator != null) {
			reader.setBeanNameGenerator(beanNameGenerator);
			scanner.setBeanNameGenerator(beanNameGenerator);
			// 注册到容器里
			beanFactory.registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
		}
		// scoope的解析器
		ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver();
		if (scopeMetadataResolver != null) {
			reader.setScopeMetadataResolver(scopeMetadataResolver);
			scanner.setScopeMetadataResolver(scopeMetadataResolver);
		}

		if (!this.componentClasses.isEmpty()) {
			if (logger.isDebugEnabled()) {
				logger.debug("Registering component classes: [" +
						StringUtils.collectionToCommaDelimitedString(this.componentClasses) + "]");
			}
			// 若是指定的Bean,就交给reder中的doRegisterBean去解析每一个 Config Bean
			reader.register(ClassUtils.toClassArray(this.componentClasses));
		}

		// 扫描配置文件的Bean
		if (!this.basePackages.isEmpty()) {
			if (logger.isDebugEnabled()) {
				logger.debug("Scanning base packages: [" +
						StringUtils.collectionToCommaDelimitedString(this.basePackages) + "]");
			}
			// 这里很重要 spring提供的包扫描功能
			scanner.scan(StringUtils.toStringArray(this.basePackages));
		}

		
	}

    ...

}

下面这个方法我就不说了吧,我在第一篇文章里已经说过了并带有完成了图例解析:

主要是Config Bean

reader.register(Class<?>... componentClasses),会循环遍历这些类,将Class转换成一个

BeanDefinition,而后解析作用域,处理通用注解(@Lazy,@Primary,@DependsOn,@Role,@Description),最后注册到BeanFactory当中。
      if (!this.componentClasses.isEmpty()) {
			if (logger.isDebugEnabled()) {
				logger.debug("Registering component classes: [" +
						StringUtils.collectionToCommaDelimitedString(this.componentClasses) + "]");
			}
			// 若是指定的Bean,就交给reder中的doRegisterBean去解析每一个 Config Bean
			reader.register(ClassUtils.toClassArray(this.componentClasses));
		}

我们继续往下看:

        // 扫描配置文件的Bean
		if (!this.basePackages.isEmpty()) {
			if (logger.isDebugEnabled()) {
				logger.debug("Scanning base packages: [" +
						StringUtils.collectionToCommaDelimitedString(this.basePackages) + "]");
			}
			// 这里很重要 spring提供的包扫描功能
			scanner.scan(StringUtils.toStringArray(this.basePackages));
		}

点开scanner.scan()方法,

这里重点看 doScan()方法。遍历basePackages,然后获取page下的所有的Class转换为

BeanDefinition,而后解析Bean的作用于,一些通过注解,最后将Bean注册到DefaultListableBeanFactory里的Map<String, BeanDefinition> beanDefinitionMap当中。

至此,将扫描包下所有的类都注册到map当中了。

到此为止,我们这个刷新工厂类就说完了。


public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {

    ......


   protected final void refreshBeanFactory() throws BeansException {
		// 如果ApplicationContext中已经加载过BeanFactory了,销毁虽有的Bean,关闭BeanFactory
		//注意:应用中BeanFactory本来就可以多个的,这里不是说应用全局是否有BeanFactory,
		// 而是当前ApplicationContext是否有BeanFactory
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			// 设置BeanFactory的两个配置属性:是否允许Bean覆盖,是否允许循环引用
			customizeBeanFactory(beanFactory);
			// 加载bean 到BeanFactory中
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

    ......


}

我们现在返回到obtainFreshBeanFactory()方法,refreshBeanFactory()我们已经说过,还剩下一个getBeanFactory();

getBeanFactory()是一个抽象方法,我们进去看:

 

这里就是把BeanFactory返回。

到此:我们整个obtainFreshBeanFactory()方法就说完了。

 

我们来总结一下:refresh()方法的前两步:

第一:标记容器为启动状态并记录启动时间,执行初始化属性源操作

第二:得到一个新的beanFactory工厂,用来保存bean容器 等同于 IOC容器,然后采用模板方法加载所有的Bean配置信息。

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小tu豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值