阅读 494

spring boot 加载过程分析(四)

AbstractApplicationContext.refresh()

refresh方法实际上调用到了AbstractApplicationContext的refresh方法。

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				destroyBeans();
				cancelRefresh(ex);
				throw ex;
			}

			finally {
				resetCommonCaches();
			}
		}
}
复制代码

首先通过获取对象锁来保证启动及关闭的同步。该方法下面做的事情就比较多了,我们需要跟踪每个方法的内部调用来分析具体做了什么。

1. prepareRefresh

通过方法名大致也能猜测到是refresh前的准备工作。比如设置启动时间,启动标识等,还有些配置环境的占位符初始化解析及必要性校验的工作。

2. obtainFreshBeanFactory

获取beanFactory容器

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
	refreshBeanFactory();
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	return beanFactory;
}
复制代码

首先refreshBeanFactory方法调用到GenericApplicationContext, 设置一个refreshed标识,然后给默认的beanFactory设置一个id;然后就是返回当前beanFactory对象(DefaultListableBeanFactory)。

3. prepareBeanFactory

beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
复制代码
  • 设置beanFactory的classLoader为当前context的classLoader
  • 设置beanFactory的表达式语言处理器,spring3增加了表达式语言的支持,默认可以使用#{bean.xxx}的形式来调用相关属性值。
  • 为beanFactory增加了一个默认的propertyEditor,这个主要是对bean的属性等设置管理的一个工具,以后再做详细分析。
  • 添加了一个处理aware相关接口的beanPostProcessor扩展ApplicationContextAwareProcessor,主要是使用beanPostProcessor的postProcessBeforeInitialization()前置处理方法会在bean实例化前进行属性注入,例如实现BeanFactoryAware的Bean在初始化后,Spring容器将会注入BeanFactory的实例。相应的还有ApplicationContextAware、ResourceLoaderAware、ServletContextAware等。
  • 设置了几个忽略自动装配的接口,默认只有BeanFactoryAware被忽略,其他的都要自行设置,这里设置了ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware和ApplicationContextAware。
  • 设置了几个自动装配的特殊规则,如果是BeanFactory类型,则注入beanFactory对象,如果是ResourceLoader、ApplicationEventPublisher、ApplicationContext类型则注入当前对象。

接着往下看

if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
    beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
    beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
复制代码

这部分判断是否定义了名为loadTimeWeaver的bean,如果定义了则添加loadTimeWeaver功能的beanPostProcessor扩展,并且创建一个临时的classLoader来让其处理真正的bean。该扩展具体是做什么的我还没深入了解,后续有时间再研究。

后面就是检查factory中是否有环境配置,系统变量等相应的bean,如果没有则注册。这里使用到了registerSingleton方法,和我们之前碰的registerBeanDefinition不一样。这里放入的直接是实例对象,不再是beanDefinition对象。

4. postProcessBeanFactory

该方法在当前类中没有具体实现,由于子类来扩展实现。按我们的环境其实现在AnnotationConfigServletWebServerApplicationContext类中。

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    super.postProcessBeanFactory(beanFactory);
    if (this.basePackages != null && this.basePackages.length > 0) {
        this.scanner.scan(this.basePackages);   
    }
    if (!this.annotatedClasses.isEmpty()) {
	this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
    }
}
复制代码

调用父类实现

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	beanFactory.addBeanPostProcessor(
		new WebApplicationContextServletContextAwareProcessor(this));
	beanFactory.ignoreDependencyInterface(ServletContextAware.class);
}
复制代码

首先是增加一个beanPostProcessor处理器,主要用于在bean初始化前后设置servlet相关配置。然后通过scanner, reader来注册beanDefinition,在我们的环境当中没有手动设置,这里不会做任何操作。

5. invokeBeanFactoryPostProcessors

访方法调用到了PostProcessorRegistrationDelegate的静态方法invokeBeanFactoryPostProcessors。代码较多,这里不再粘贴,大致介绍一下方法流程。

  • 首先通过getBeanFactoryPostProcessors查找手动配置的beanFactory后置处理器。(在前面分析的Initializer和listener中增加)
  • 判断其是否实现BeanDefinitionRegistryPostProcessor接口,如果是则先执行postProcessBeanDefinitionRegistry方法,并区分暂存到两个集合当中。BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子接口。
  • 通过beanFactory的getBeanNamesForType方法来查找容器中BeanDefinitionRegistryPostProcessor的实现,然后按优先级及排序,非排序等分别执行。
  • 把BeanDefinitionRegistryPostProcessor接口的方法都执行完成后,再分别执行其BeanFactoryPostProcessor接口的方法(这里包括手动配置及容器中查找的),并记录名字到集合。
  • 同样的流程,在容器中查找BeanFactoryPostProcessor的实现,并按做优先级,排序等分别执行,这里会检验跳过上面已执行过的。

简单描述下,就是先查找BeanDefinitionRegistryPostProcessor接口实现并执行postProcessBeanDefinitionRegistry方法,然后再查找执行BeanFactoryPostProcessor接口的实现,并执行postProcessBeanFactory方法。

6. registerBeanPostProcessors

通过方法名可以理解,就是注册BeanPostProcessor实现类的。调用到PostProcessorRegistrationDelegate的方法。代码如下:

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
复制代码

这里注意一下与以上一篇介绍的BeanFactoryPostProcessro接口的区别,BeanPostProcessor主要是针对bean初始化前后的扩展,具体可以自行百度下,网上资料较多。

public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
                // 查找BeanPostProcessor实现的名称
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

		// 添加BeanPostProcessorChecker,用于打印日志提示在BeanPostProcessor实例化期间新建bean,不能被全部的BeanPostProcessor实例处理
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

		// 按优先级,排序,非排序等分类调用.
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
			        // 实例化
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);
				// 记录内部处理
				if (pp instanceof MergedBeanDefinitionPostProcessor) {
					internalPostProcessors.add(pp);
				}
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// 先是优先级高的
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// 再是实现排序的
		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
		for (String ppName : orderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			orderedPostProcessors.add(pp);
			// 记录内部处理
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);

		// 然后是普通的
		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
		for (String ppName : nonOrderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			nonOrderedPostProcessors.add(pp);
			// 记录内部处理
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

		// 最后是MergedBeanDefinitionPostProcessor的实现
		sortPostProcessors(internalPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		// 最最后增加一个关于ApplicationListener的探测类
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}
复制代码

这里registerBeanPostProcessors方法最后会调用到AbstractBeanFactory的addBeanPostProcessor方法,其实现是先删后加,所以上面MergedBeanDefinitionPostProcessor的实现不会重复添加,只是把其处理优先级放到了最后。这里又碰到那个很重要的方法getBean,关于该方法暂时不讨论了,有兴趣的要以先自行搜索查询了解下。

7. initMessageSource

初始化消息资源的默认空处理DelegatingMessageSource。

8. initApplicationEventMulticaster

初始化ApplicationListener的事件发布器简单实现

9. onRefresh

该方法主要由AbstractApplicationContext子类来扩展实现,因为我们的web服务,所以由于ServletWebServerApplicationContext实现,主要是实例化web服务,比如ServletContext上下文配置,tomcat初始化配置等。

protected void onRefresh() {
	super.onRefresh();
	try {
	    createWebServer();
	}
	catch (Throwable ex) {
	    throw new ApplicationContextException("Unable to start web server", ex);
	}
}
复制代码

10. registerListeners

查找注册ApplicationListener实现的监听器

11. finishBeanFactoryInitialization

该方法其实就是遍历BeanFacotry当中的BeanDefinition数据,然后调用getBean方法来实例化及依赖注入等,完成容器所有bean的实例化工作。

12. finishRefresh

完成刷新工作,清除缓存;注册LifecycleProcessor的实现DefaultLifecycleProcessor并调用onRefresh方法;发布刷新事件;启动web服务等。

在整个refresh方法的最后,就是调用各种清除缓存的方法了。

备注:本章涉及三点实现较为复杂,需要着重来分析,所以后面会单章来看这几部分具体做了哪些工作

  1. ConfigurationClassPostProcessor类
  2. getBeanNamesForType方法
  3. getBean方法

参考连接: blog.csdn.net/yuxj1988/ar…

文章分类
后端