spring5.0.5初始化源码学习三部曲之三:AbstractApplicationContext.refresh()方法

本章是《spring初始化源码学习三部曲》系列的终章,重点是学习AbstractApplicationContext.refresh()方法;

我们先来回顾ClassPathXmlApplicationContext类的初始化过程如下代码:

public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz, @Nullable ApplicationContext parent) throws BeansException {
        super(parent);
        Assert.notNull(paths, "Path array must not be null");
        Assert.notNull(clazz, "Class argument must not be null");
        this.configResources = new Resource[paths.length];

        for(int i = 0; i < paths.length; ++i) {
            this.configResources[i] = new ClassPathResource(paths[i], clazz);
        }

        this.refresh();
    }

三部曲的前两篇学习了supper(parent)setConfigLocations(configLocations)
1:《spring5.0.5初始化源码三部曲之一:AbstractApplicationContext构造方法》
2:《spring5.0.5初始化源码三部曲之二:setConfigLocations方法》

refresh()方法简介

本章来学习refresh方法,具体的源码在AbstractApplicationContext类中,该方法的简介请看源码中的注解:

	@Override
	public void refresh() throws BeansException, IllegalStateException {
//		startupShutdownMonitor对象在spring环境刷新和销毁的时候都会用到,确保刷新和销毁不会同时执行
		synchronized (this.startupShutdownMonitor) {
// 		准备工作:例如记录事件,设置标志,检查环境变量,并有留给子类扩展的位置,用来将属性加入到ApplicationContext中
			prepareRefresh();
//		创建beanFactory,这个对象作为applicationContext的成员变量,可以被applicationContext拿来用
//		并且解析资源(例如xml文件),取得bean定义,放在beanFactor中
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//		对beanFactory做一些设置,例如类加载器,spel解析器,指定bean的某些类型的成员变量对应某些对象等
			prepareBeanFactory(beanFactory);
			try {
				//子类扩展用,可以设置bean的后置处理器(bean在实例化之后这些后置处理器会执行)
				postProcessBeanFactory(beanFactory);
				// 执行beanFactory后置处理器(有别于bean后置处理器处理bean实例,beanFactory后置处理器处理bean定义)
				invokeBeanFactoryPostProcessors(beanFactory);
				//将所有的bean的后置处理器排好序,但不会马上用,bean实例化之后会用到
				registerBeanPostProcessors(beanFactory);
				//初始化国际化服务
				initMessageSource();
				//创建事件广播器
				initApplicationEventMulticaster();
				//空方法,留给子类自己实现的,在实例化bean之前做一些ApplicationContext相关操作
				onRefresh();
				//注册一部分特殊的事件监听器,剩下的只是准备好名字,留待bean实例化完成后再注册
				registerListeners();
				//单例模式的bean的实例化,成员变量注入,初始化等工作都在此完成
				finishBeanFactoryInitialization(beanFactory);
				//最后一步:applicationContext刷新完成后的处理,例如生命周期监听器的回调,广播通知等
				finishRefresh();
			} catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}
				//刷新失败后的处理,主要是将一些保存环境信息的集合做清理
				destroyBeans();
				//重置“活动”标志
				cancelRefresh(ex);
				//将异常传播到调用方
				throw ex;
			} finally {
				//重置spring核心的常见内省缓存,因为我们可能永远不会
				resetCommonCaches();
			}
		}
	}

接下来逐个分析吧:

prepareRefresh()方法的源码如下:

	protected void prepareRefresh() {
//		记录初始化开始时间
		this.startupDate = System.currentTimeMillis();
//		context是否关闭的标志,设置flase(开启标记)
		this.closed.set(false);
//		context是否激活的标记,设置为true
		this.active.set(true);
		if (logger.isInfoEnabled()) {
			logger.info("Refreshing " + this);
		}
//		留给子类实现的空方法
		initPropertySources();
//		AbstractPropertyResolver类的requiredProperties是个集合,
//		在下面的validateRequeiredProperties()方法中,都要拿requiredProperties中的元素作为key去检查是否存在对应的环境变量。
//		如果不存在就抛出异常
		getEnvironment().validateRequiredProperties();
		//允许收集早期的ApplicationEvents,一旦多播可用,将发布
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}

上述代码中,注意一下两处:

  1. initPropertySources()空方法,是留给子类实现的,以AnnotationConfigWebApplicationContext类为例,initPropertySources方法:
	@Override
	protected void initPropertySources() {
		ConfigurableEnvironment env = getEnvironment();
		if (env instanceof ConfigurableWebEnvironment) {
			((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, this.servletConfig);
		}
	}

跟踪上面的方法,最终找到了WebApplicationContextUtils.initServletPropertySources方法:

	public static void initServletPropertySources(MutablePropertySources sources,
			@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {

		Assert.notNull(sources, "'propertySources' must not be null");
		String name = StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME;
		if (servletContext != null && sources.contains(name) && sources.get(name) instanceof StubPropertySource) {
			sources.replace(name, new ServletContextPropertySource(name, servletContext));
		}
		name = StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME;
		if (servletConfig != null && sources.contains(name) && sources.get(name) instanceof StubPropertySource) {
			sources.replace(name, new ServletConfigPropertySource(name, servletConfig));
		}
	}

上面的代码所做的事情:就是给context增加环境变量数据(数据来自Servlet相关的配置信息),这样spring环境就能从context中key取得对应的变量了;

  1. getEnvironment().validateRequiredProperties();的作用是用来检测context中是否存在“某些”变量,何为“某些”?来看validateRequiredProperties方法,追踪到多层调用,最终在AbstractPropertyResolver类的validateRequiredProperties方法中实现:
	@Override
	public void validateRequiredProperties() {
		MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
		for (String key : this.requiredProperties) {
			if (this.getProperty(key) == null) {
				ex.addMissingRequiredProperty(key);
			}
		}
		if (!ex.getMissingRequiredProperties().isEmpty()) {
			throw ex;
		}
	}

上述代码显示:如果集合requiredProperties的name在context中找不到对用变量,就会抛出异常;
那么问题来了,requiredPropertys是何时设置的呢?spring-framework中并没有调用,但是官方的单元测试源码给我们了启示,如下图:

在这里插入图片描述
如图所示:如果业务需要确保某些变量在spring环境中存在,就可以通过setRequiredProperty方法将变量的name传递进去,这样validateRequiredProperty方法就可以检查了,我们可以基于现有的各种ApplicationContext实现自己定制一个context类,确保在validateRequiredProperty方法调用之前,调用setRequiredProperty方法将变量name传入进去(比如重写),这样spring就能帮我们完成检查;

ObtainFreshBeanFactory()

接下来看ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();得到临时变量beanFactory,先看看beanFactory和ConfiguarableListableBeanFactory的关系:

在这里插入图片描述
在看看ObtainFreshBeanFactory方法:

	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//		由子类创建beanFactory
		refreshBeanFactory();
//		取得子类创建好的beanFactory,作为obtainFreshBeanFactory方法的返回值
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (logger.isDebugEnabled()) {
			logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
		}
		return beanFactory;
	}

上述代码中refreshBeanFactory需要细看:

refreshBeanFactory()

refreshBeanFactory方法,在AbstractApplicationContext中是抽象方法,具体实现在子类中,以其子类AbstractRefreshApplicationContext为例,我们来看看refreshBeanFactory方法:

	@Override
	protected final void refreshBeanFactory() throws BeansException {
//		如果beanFactory已经存在,就销毁context管理的所有bean,并关闭beanFactory
		if (hasBeanFactory()) {
//			销毁所有bean,其实就是调用一些集合的clear方法,解除对一些实例的引用
			destroyBeans();
//			关闭beanFactory,其实就是将成员变量beanFactory设置为null
			closeBeanFactory();
		}
		try {
//			创建IoC容器
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
//			对IoC容器进行定制化,如设置启动参数,开启注解的自动装配等
			customizeBeanFactory(beanFactory);
//			调用载入Bean定义的方法,主要这里又使用了一个委派模式,
//			在当前类中只定义了抽象的loadBeanDefinitions方法,
//			具体的实现调用子类容器
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}
  1. createBeanFactory()方法实际上返回的是DefaultListableBeanFactory实例:
protected DefaultListableBeanFactory createBeanFactory() {
		return new DefaultListableBeanFactory(getInternalParentBeanFactory());
	}
  1. 接下来customizeBeanFactory(beanFactory);方法是留给子类override的,该方法的说明和源码如下,说明中推荐通过override的方式对现有beanFactory做特别设置:
	protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
//		allowBeanDefinitionOverriding表示是否允许注册一个同名的类来覆盖原有类(注意是类,不是实例)
		if (this.allowBeanDefinitionOverriding != null) {
			beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
		}
//		allowCircularReferences表示是否运行多个类之间的循环引用
		if (this.allowCircularReferences != null) {
			beanFactory.setAllowCircularReferences(this.allowCircularReferences);
		}
	}
  1. loadBeanDefinitions(beanFactory)在AbstractRefreshApplicationContext类中是个抽象方法,留给子类实现,作用是把所有bean的定义后保存在context中,以AbstractXmlApplicationContext为例,看看loadBeanDefinitions方法:
	@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
//		创建XmlBeanDefinitionReader,即创建Bean读取器,并通过回调设置到容器中去,容  器使用该读取器读取Bean定义资源
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// Configure the bean definition reader with this context's
		// resource loading environment.
//		为Bean读取器设置Spring资源加载器,AbstractXmlApplicationContext的
//		祖先父类AbstractApplicationContext继承DefaultResourceLoader,因此,容器本身也是一个资源加载器
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		// Allow a subclass to provide custom initialization of the reader,
		// then proceed with actually loading the bean definitions.
//		当Bean读取器读取Bean定义的Xml资源文件时,启用Xml的校验机制
		initBeanDefinitionReader(beanDefinitionReader);
//		Bean读取器真正实现加载的方法
		loadBeanDefinitions(beanDefinitionReader);
	}

以上代码可见,加载bean的定义是通过XmlBeanDefinitionReader完成,重点关注loadBeanDefinitions(beanDefinitionReader)方法:

	protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			reader.loadBeanDefinitions(configResources);
		}
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
	}

上述代码中getConfigResources和getConfigLocations,究竟哪个返回有效数据?这就要看ClassPathXmlApplicationContext的构造方法了:

//这个方法设置的是configLocations 
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
            throws BeansException {

    super(parent);
    setConfigLocations(configLocations);
    if (refresh) {
        refresh();
    }
}

//这个方法设置的是这个方法设置的是configResources 
public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz, ApplicationContext parent)
            throws BeansException {

    super(parent);
    Assert.notNull(paths, "Path array must not be null");
    Assert.notNull(clazz, "Class argument must not be null");
    this.configResources = new Resource[paths.length];
    for (int i = 0; i < paths.length; i++) {
        this.configResources[i] = new ClassPathResource(paths[i], clazz);
    }
    refresh();
}

因此,到底是configLocations 还是configResources ,和我们使用哪个构造方法来实例化applicationContext对象有关;

  1. 如果我们实例化Application对象的方法是new ClassPathXmlApplicationContext(“applicationsContext.xml”) ,那么setConfigLocations方法就会被调用,因此loadBeanDefinitions方法内部,实际执行的代码如下:
String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
  1. 现在可以看AbstractBeanDefinitionReader类的loadBeanDefinitions(String…locations)方法了:
	@Override
	public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
		Assert.notNull(locations, "Location array must not be null");
		int counter = 0;
		for (String location : locations) {
			counter += loadBeanDefinitions(location);
		}
		return counter;
	}

展开上面for循环调用的方法:

public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
		ResourceLoader resourceLoader = getResourceLoader();
		if (resourceLoader == null) {
			throw new BeanDefinitionStoreException(
					"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
		}

		if (resourceLoader instanceof ResourcePatternResolver) {
			// Resource pattern matching available.
			try {
				Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
				int loadCount = loadBeanDefinitions(resources);
				if (actualResources != null) {
					for (Resource resource : resources) {
						actualResources.add(resource);
					}
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
				}
				return loadCount;
			}
			catch (IOException ex) {
				throw new BeanDefinitionStoreException(
						"Could not resolve bean definition resource pattern [" + location + "]", ex);
			}
		}
		else {
			// Can only load single resources by absolute URL.
			Resource resource = resourceLoader.getResource(location);
			int loadCount = loadBeanDefinitions(resource);
			if (actualResources != null) {
				actualResources.add(resource);
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
			}
			return loadCount;
		}
	}

以上方法中,首先要记得ResourceLoader是ClassPathXmlApplicationContext(beanDefinitionReader.setResourceLoader(this);这行代码),所有resourceLoader.getResource(location)这行代码最终都会调用PathMatchingResourcePatternResolver类的getResource(String locationPattern)方法得到bean有关的Resource对象;得到Resource对象后,接着会调用loadBeanDefinitions(Resource… resources)方法来加载bean的定义,最终会调用XmlBeanDefinitionReader.loadBeanDefinitions(EncodedResource encodedResource)方法:

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		Assert.notNull(encodedResource, "EncodedResource must not be null");
		if (logger.isInfoEnabled()) {
			logger.info("Loading XML bean definitions from " + encodedResource.getResource());
		}

		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
		if (currentResources == null) {
			currentResources = new HashSet<>(4);
			this.resourcesCurrentlyBeingLoaded.set(currentResources);
		}
		if (!currentResources.add(encodedResource)) {
			throw new BeanDefinitionStoreException(
					"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
		}
		try {
			InputStream inputStream = encodedResource.getResource().getInputStream();
			try {
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			}
			finally {
				inputStream.close();
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"IOException parsing XML document from " + encodedResource.getResource(), ex);
		}
		finally {
			currentResources.remove(encodedResource);
			if (currentResources.isEmpty()) {
				this.resourcesCurrentlyBeingLoaded.remove();
			}
		}
	}

上述代码可见,重要的是通过resource对象得到流InputStream,再调用doLoadBeanDefinitions方法:

/*从特定xml文件中实际载入Bean定义资源的方法*/
	protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
		try {
//			将xml文件转换为DOM对象,解析过程由doLoadDocument实现
			Document doc = doLoadDocument(inputSource, resource);
//			这里是启动对bean定义解析的详细过程,该解析过程会用到spring的Bean配置规则
			return registerBeanDefinitions(doc, resource);
		}
		......................
	}

上述代码是加载bean定义的关键代码:先制作Document对象,再调用registerBeanDefinitions,最终会将每个bean的定义放入DefaultListableBeanFactory的beanDefinitionMap中,详细的堆栈如下图:
在这里插入图片描述
完成bean定义注册,可以回到AbstractRefreshApplicationContext.refreshBeanFactory方法上,看看loadBeanDefinition(beanFactory)之后的代码:

synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}

至此,refreshBeanFactory()方法分析完毕,该方法所做的事情:把xml文件中的bean定义被解析后,存放在DefaultListableApplicationContext的beanDefinitonMap中;
现在回到主线AbstractApplicationContext.refresh()方法内,obtainRefreshBeanFactory()已经分析完毕,所有bean定义都存放在beanFactory这个临时变量实例中;

prepareBeanFactory

接下来prepareBeanFactory(beanFactory),看一下此方法的源码:

	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// Tell the internal bean factory to use the context's class loader etc.
//		设置类加载器
		beanFactory.setBeanClassLoader(getClassLoader());
//		设置解析器,用于解析bean的定义中出现的Spel表达式
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//		添加属性编辑器,更准确应该是属性转换器,比如从String到Date类型的 转化
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Configure the bean factory with context callbacks.
//		添加后置处理器
		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 interface not registered as resolvable type in a plain factory.
		// MessageSource registered (and found for autowiring) as a bean.
//		设置几个自动装配规则,例如如果是BeanFactory则注入beanFactory
		//如果是ResourceLoader,ApplicationEventPublisher,ApplicationContext注入当前对象
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

		// Register early post-processor for detecting inner beans as ApplicationListeners.
//
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// Detect a LoadTimeWeaver and prepare for weaving, if found.
		if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			// Set a temporary ClassLoader for type matching.
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}

		// Register default environment beans.
		if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
		}
	}

上述代码中有以下几点需要注意:

  1. beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())),此方法要配合AbstractBeanFactory.registerCustomEditors方法一起看更好理解:addPropertyEditorRegistrar方法向propertyEditorRegistrars属性中放入了一个registrar,之后调用registerCustomEditors方法的时候,会用到propertyEditorRegistrars中的registrar,调用这些registrar的registerCustomEditors方法,完成自定义的转换器的设置;
  2. beanFactory.addBeanPostProcessor方法用来注入后置处理器,在bean实例被创建后,初始化方法被执行的前后,后置处理器的postProcessBeforeInitialization、postProcessAfterInitialization这两个方法会分别被调用;
  3. beanFactory.ignoreDependencyInterface设置了依赖注入时要忽略的接口,例如bean有个属性类型是ResourceLoaderAware,那么该属性不会被注入ResourceLoaderAware类型的实例;
  4. beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory)是特殊设置,如果一个bean有个属性的类型是BeanFactory,那么该属性会被设置为beanFactory这个实例;
    总的来说prepareBeanFactory方法就是为beanFactory做一些设置工作,传入一些后面会用到的参数和工具类,再在spring容器中创建一些bean;

postProcessBeanFactory

postProcessBeanFactory方法是留给子类扩展的,可以在bean实例初始化之前注册后置处理器(类似prepareBeanFactory方法中的beanFactory.addBeanPostProcess);

invokeBeanFactoryPostProcessor

invokeBeanFactoryPostProcessor方法用来执行beanFactory实例的后置处理器beanFactoryPostProcessor的postProcessBeanFactory方法,这个后置处理器除了原生,我们也可以自己扩展,用来给bean的定义做些修改,由于此时bean还没有实例化,所有不要在自己扩展的beanFactoryPostProcessor中调用那些会触发bean实例化的方法(例如beanFactoy的getBeanNamesForType方法);

registerBeanPostProcessors

registerBeanPostProcessors方法的代码略多,就不在此贴出来了,简单的说,就是找出所有的bean的后置处理器(注意,是bean的后置处理器,不是beanFactory的后置处理器,bean后置处理器处理的是bean实例,beanfactory后置处理器处理的是bean的定义),然后将这些bean的后置处理器分为三类:

  1. 实现了顺序接口Ordered.class的,先放入orderedPostProcessors集合,排序后顺序加入beanFactory的bean后处理集合中;
  2. 既没有实现Ordered.class,也没有实现PriorityOrdered.class的后置处理器,也加入到beanFactory的bean后处理集合中;
  3. 最后是实现了优先级接口PriorityOrdered.class的,排序后顺序加入beanFactory的bean后处理集合中;
    registerBeanPostProcessors方法执行完毕,beanFactory中保存了有序的bean后置处理器,在bean实例化之后,会依次使用这些后置处理器对bean实例进行对应处理;

InitMessageSource

initMessageSource方法用来准备国际化资源相关的,将实现MessageSource接口的bean存放在ApplicationContext的成员变量中,先看是否有配置,如果有就实例化,否则就创建一个DelegatingMessageSource实例的bean;

InitApplicationEventMulticaster

spring中有事件,事件广播器,事件监听器等组成事件体系,在initApplicationEventMulticaster中对事件广播器做了初始化,如果找不到此bean的配置,就创建一个SimpleApplicationEventMulticaster实例作为事件广播器的bean,并保存到ApplicationContext成员变量ApplicationEventMulticaster;

Onfresh

Onfresh是个空方法,留给子类来实现,在实例化bean之前做一些ApplicationContext相关的操作;

registerListener

方法名是registerListener,看名字好像是将监听器注册到事件广播器中,但实际情况并非如此,只有一些特殊的监听器注册了,那些bean配置文件中实现了ApplicationListener接口的类还没实例化,所以此处只是将其name保存在广播器中,将这些监听器注册到广播器的操作是在bean后置处理器中完成的,那时候bean实例化已经完成了,我们看代码:

protected void registerListeners() {
        Iterator var1 = this.getApplicationListeners().iterator();
//      注册的都是特殊的事件监听器,而并非配置的bean
        while(var1.hasNext()) {
            ApplicationListener<?> listener = (ApplicationListener)var1.next();
            this.getApplicationEventMulticaster().addApplicationListener(listener);
        }
//		根据接口类型找到所有监听器的名称
        String[] listenerBeanNames = this.getBeanNamesForType(ApplicationListener.class, true, false);
        String[] var7 = listenerBeanNames;
        int var3 = listenerBeanNames.length;		
        for(int var4 = 0; var4 < var3; ++var4) {
//        这里只是将监听器的名称保存在广播器中,并没有将这些监听器实例化
            String listenerBeanName = var7[var4];		this.getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
        }

        Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
        this.earlyApplicationEvents = null;
        if (earlyEventsToProcess != null) {
            Iterator var9 = earlyEventsToProcess.iterator();

            while(var9.hasNext()) {
                ApplicationEvent earlyEvent = (ApplicationEvent)var9.next();
                this.getApplicationEventMulticaster().multicastEvent(earlyEvent);
            }
        }

    }

finishBeanFactoryInitialization

finishBeanFactoryInitialiazation方法做了两件事:
beanFactory实例的初始化;
我们在bean配置文件中配置的那些单例的bean,都是在finishBeanFactoryInitialization方法中实例化的;看代码:

    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    //  实例化类型转换的bean,并保存在ApplicationContext中
        if (beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) {
            beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class));
        }
        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver((strVal) -> {
                return this.getEnvironment().resolvePlaceholders(strVal);
            });
        }
//      实例化LoadTimeWeaverAware接口的bean,用于ApsectJ的类加载期织入的处理
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        String[] var3 = weaverAwareNames;
        int var4 = weaverAwareNames.length;
        for(int var5 = 0; var5 < var4; ++var5) {
            String weaverAwareName = var3[var5];
            this.getBean(weaverAwareName);
        }
        // 确保临时的classLoader为空,临时classLoader一般被用来做类型匹配的
        beanFactory.setTempClassLoader((ClassLoader)null);
        // 将一个标志设置为true,表示applicationContext已经缓存了所有bean的定义,这些bean的name都被保存在applicationContext的frozenBeanDefinitionNames成员变量中,相当于一个快照,记录了当前那些bean的定义已经拿到了
        beanFactory.freezeConfiguration();
        // 实例化所有还未实例化的单例bean
        beanFactory.preInstantiateSingletons();
    }

上述代码中:beanFactory.preInstantiateSingletions()需要展开仔细看:

public void preInstantiateSingletons() throws BeansException {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Pre-instantiating singletons in " + this);
        }

        List<String> beanNames = new ArrayList(this.beanDefinitionNames);
        Iterator var2 = beanNames.iterator();

        while(true) {
            String beanName;
            Object bean;
            do {
                while(true) {
                //获取bean的定义
                    RootBeanDefinition bd;
                    do {
                        do {
                            do {
                                if (!var2.hasNext()) {
                                    var2 = beanNames.iterator();

                                    while(var2.hasNext()) {
                                        beanName = (String)var2.next();
                                        Object singletonInstance = this.getSingleton(beanName);
                                        if (singletonInstance instanceof SmartInitializingSingleton) {
                                            SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton)singletonInstance;
                                            if (System.getSecurityManager() != null) {
                                                AccessController.doPrivileged(() -> {
                                                    smartSingleton.afterSingletonsInstantiated();
                                                    return null;
                                                }, this.getAccessControlContext());
                                            } else {
                                                smartSingleton.afterSingletonsInstantiated();
                                            }
                                        }
                                    }

                                    return;
                                }

                                beanName = (String)var2.next();
                                bd = this.getMergedLocalBeanDefinition(beanName);
                            } while(bd.isAbstract());
                        } while(!bd.isSingleton());
                    } while(bd.isLazyInit());
					//FactoryBean的处理
                    if (this.isFactoryBean(beanName)) {
                        bean = this.getBean("&" + beanName);
                        break;
                    }
					//非FactoryBean的实例化、初始化
                    this.getBean(beanName);
                }
            } while(!(bean instanceof FactoryBean));

            FactoryBean<?> factory = (FactoryBean)bean;
            boolean isEagerInit;
            if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                SmartFactoryBean var10000 = (SmartFactoryBean)factory;
                ((SmartFactoryBean)factory).getClass();
                isEagerInit = (Boolean)AccessController.doPrivileged(var10000::isEagerInit, this.getAccessControlContext());
            } else {
                isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean)factory).isEagerInit();
            }

            if (isEagerInit) {
                this.getBean(beanName);
            }
        }
    }

上述代码中,要重点关注this.getBean(beanName),这里面会实例化bean,由于内容太多不适合在本章细说,这里先将实例化bean的调用路径整理出来:
在这里插入图片描述

finishRefresh

最后一个方法是finishRefresh,这是在bean的实例化、初始化等完成后的一些操作,例如生命周期变更的回调,发送applicationContext刷新完成的广播等,展开看看:

protected void finishRefresh() {
    // 检查是否已经配置了生命周期处理器,如果没有就new一个DefaultLifecycleProcessor
    initLifecycleProcessor();

    // 找到所有实现了Lifecycle接口的bean,按照每个bean设置的生命周期阶段进行分组,再依次调用每个分组中每个bean的start方法,完成生命周期监听的通知
    getLifecycleProcessor().onRefresh();

    // 创建一条代表applicationContext刷新完成的事件,交给广播器去广播
    publishEvent(new ContextRefreshedEvent(this));

    // 如果配置了MBeanServer,就完成在MBeanServer上的注册
    LiveBeansView.registerApplicationContext(this);
}

至此,整个初始化流程咱们已经过了一遍了,但是篇幅有限,很多细节都没有展开,另外很多子类也有自己独特的扩展,这些都需要花时间去细看,希望本文能帮您整理思路,从总体上了解初始化的各个关键步骤,以免过早陷入细节;

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值