likes
comments
collection
share

(五)Spring源码解析:ApplicationContext源码解析

作者站长头像
站长
· 阅读数 29

一、概述

1.1> 整体概览

在前面的内容中,我们针对BeanFactory进行了深度的分析。那么,下面我们将针对BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与BeanFactory的功能相似,都是用于向IOC中加载Bean的。由于ApplicationConext的功能是大于BeanFactory的,所以在日常使用中,建议直接使用ApplicationConext即可。下面是两个类使用示例:

(五)Spring源码解析:ApplicationContext源码解析

ApplicationConext是接口,所以要分析其加载bean的流程,就可以从ClassPathXmlApplicationContext入手,其构造函数如下所示:

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
	this(new String[] {configLocation}, true, null);
}

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) {
	super(parent);
	setConfigLocations(configLocations); // 事情1:设置配置加载路径
	if (refresh) refresh(); // 事情2:所有功能的初始化操作
}

在上面的构造方法中,主要做了两个事情: 【事情1】设置配置的加载路径; 【事情2】执行ApplicationConext中,所有功能的初始化操作; 下面文章的内容,我们就是会针对这两部分做详细的解析:

1.2> setConfigLocations(...) 设置配置加载路径

该方法逻辑不多,主要就是为应用上下文ApplicationContext设置配置路径(config locations),源码如下所示:

public void setConfigLocations(String... locations) { // 支持传入多个配置文件
	if (locations != null) {
		this.configLocations = new String[locations.length];
		for (int i = 0; i < locations.length; i++) 
			this.configLocations[i] = resolvePath(locations[i]).trim(); // 路径解析
	} else 
        this.configLocations = null;
}

// 如果路径中包含特殊符号(如:${var}),那么在resolvePath方法中会搜寻匹配的系统变量并且进行替换操作
protected String resolvePath(String path) {
    // 调用AbstractPropertyResolver#resolveRequiredPlaceholders(path)方法
    return getEnvironment().resolveRequiredPlaceholders(path); 
}

1.3> refresh() 初始化

refresh()方法中几乎包含了ApplicationContext中提供的全部功能,下面我们会针对这个方法进行详细的分析:

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		prepareRefresh(); /** 步骤1:为refresh操作做提前的准备工作 */
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); /** 步骤2:获得beanFactory实例对象 */
		prepareBeanFactory(beanFactory); /** 步骤3:准备用于此上下文的beanFactory */
		try {
			postProcessBeanFactory(beanFactory); // 允许在上下文子类中对BeanFactory进行后置处理(空方法,可由子类实现)
			invokeBeanFactoryPostProcessors(beanFactory); /** 步骤4:激活各种BeanFactory的后置处理器 */
			registerBeanPostProcessors(beanFactory); /** 步骤5:注册各种Bean的后置处理器,在getBean时才会被调用 */
			initMessageSource(); /** 步骤6:为上下文初始化消息源(即:国际化处理)*/
			initApplicationEventMulticaster(); /** 步骤7:为上下文初始化应用事件广播器 */
			onRefresh(); // 初始化特定上下文子类中的其他特殊bean(空方法,可由子类实现)
			registerListeners(); /** 步骤8:在所有注册的bean中查找listener bean,并注册到消息广播器中 */
			finishBeanFactoryInitialization(beanFactory); /** 步骤9:初始化剩下的单例(非惰性non-lazy-init)*/
			finishRefresh(); /** 步骤10:完成refresh,通知lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知 */
		}
		catch (BeansException ex) {
			destroyBeans(); // Destroy already created singletons to avoid dangling resources
			cancelRefresh(ex); // Reset 'active' flag
			throw ex;
		}
		finally {resetCommonCaches();}
	}
}

二、prepareRefresh()准备工作

下面我们来分析一下refresh()方法中的prepareRefresh()代码段的处理逻辑:

(五)Spring源码解析:ApplicationContext源码解析

针对prepareRefresh()方法来说,主要就包含如下注释的两个方法,看似没什么意义,但是如果我们自定义了ClassPathXmlApplicationContext类,那么可以通过重写initPropertySources()方法,来增加逻辑代码:

protected void prepareRefresh() {
	...
	this.active.set(true); 
	initPropertySources(); // 空方法,可以由子类重写
	getEnvironment().validateRequiredProperties(); /** 验证需要的属性文件是否都已经放入环境中 */
	...
}
public void validateRequiredProperties() throws MissingRequiredPropertiesException {
	this.propertyResolver.validateRequiredProperties();
}
public void validateRequiredProperties() {
	MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
	for (String key : this.requiredProperties) 
        // 如果环境中没有配置所需属性,则将缺失的属性放到ex中,并抛出异常
		if (this.getProperty(key) == null) 
            ex.addMissingRequiredProperty(key); 
	if (!ex.getMissingRequiredProperties().isEmpty()) {throw ex;}
}

三、obtainFreshBeanFactory()获得最新BeanFactory

下面我们来分析一下refresh()方法中的obtainFreshBeanFactory()代码段的处理逻辑:

(五)Spring源码解析:ApplicationContext源码解析

通过obtainFreshBeanFactory()这个方法,ApplicationContext就已经拥有了BeanFactory的全部功能。而这个方法中也包含了前面我们介绍BeanFactory时候对于xml配置的加载过程。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
	refreshBeanFactory(); /** 初始化BeanFactory */
	return getBeanFactory(); 
}

refreshBeanFactory()方法中,在基本容器的基础上,增加了是否允许覆盖是否允许扩展的设置,并提供了注解 @Qualifier@Autowired 的支持。

protected final void refreshBeanFactory() throws BeansException {
	if (hasBeanFactory()) {destroyBeans();closeBeanFactory();}

	try {
		DefaultListableBeanFactory beanFactory = createBeanFactory(); // new一个beanFactory的实例对象
		beanFactory.setSerializationId(getId());
		customizeBeanFactory(beanFactory); // 定制化操作BeanFactory配置
		loadBeanDefinitions(beanFactory); /** 初始化XmlBeanDefinitionReader,并进行xml配置文件读取及解析 */
		this.beanFactory = beanFactory;
	}
	catch (IOException ex) {throw new ApplicationContextException(...);}
}

/** 该方法可以采用子类覆盖的方式改变里面的逻辑内容 */
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
	if (this.allowBeanDefinitionOverriding != null) // 设置是否允许覆盖同名称且不同定义的beanDefinition实例
		beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
	if (this.allowCircularReferences != null) // 设置是否允许bean直接存在循环依赖
		beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}

loadBeanDefinitions(beanFactory)方法中,执行了初始化XmlBeanDefinitionReader操作,并且进行xml配置文件读取及解析

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // 创建XmlBeanDefinitionReader,用于后续对配置的读取操作
	XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
	beanDefinitionReader.setEnvironment(this.getEnvironment());
	beanDefinitionReader.setResourceLoader(this);
	beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

	initBeanDefinitionReader(beanDefinitionReader); // 对beanDefinitionReader进行设置,可以被子类覆盖
	loadBeanDefinitions(beanDefinitionReader); /** 加载xml配置信息 */
}

/** 对XmlBeanDefinitionReader进行设置(此方法可以由子类进行覆写) */
protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
	reader.setValidating(this.validating); // validating = true
}

当获得了XmlBeanDefinitionReader之后,我们就可以通过loadBeanDefinitions(beanDefinitionReader)方法对xml配置文件进行读取操作了。其中的reader.loadBeanDefinitions(...)方法我们在前面的BeanFactory配置文件读取操作中已经解析过了,此处就不再赘述。

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
	// 尝试获得xml配置文件的Resource实例集合,并进行配置加载
    Resource[] configResources = getConfigResources();  
	if (configResources != null) reader.loadBeanDefinitions(configResources);

    // 尝试获得xml配置文件路径集合,并进行配置加载
	String[] configLocations = getConfigLocations(); 
	if (configLocations != null) reader.loadBeanDefinitions(configLocations);
}

四、prepareBeanFactory(...)准备用于此上下文的beanFactory

4.1> 整体概览

下面我们来分析一下refresh()方法中的prepareBeanFactory()代码段的处理逻辑:

(五)Spring源码解析:ApplicationContext源码解析

当执行本方法之前,Spring已经完成了对配置的解析操作,而从本方法开始,ApplicationContext在功能上的扩展也由此展开了。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	// 将当前上下文的classLoader作为beanFactory的classLoader
    beanFactory.setBeanClassLoader(getClassLoader()); 

	// 是否支持SpEL表达式解析,即:可以使用#{bean.xxx}的形式来调用相关属性值
	if (!shouldIgnoreSpel) 
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));

	// 添加1个属性编辑器,它是对bean的属性等设置管理的工具
	beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

	// 添加1个bean的后置处理器
	beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); 

	// 设置7个需要忽略自动装配的接口
	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.ignoreDependencyInterface(ApplicationStartupAware.class);

	// 注册4个依赖
	beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
	beanFactory.registerResolvableDependency(ResourceLoader.class, this);
	beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
	beanFactory.registerResolvableDependency(ApplicationContext.class, this);

	// 添加1个bean的后置处理器
	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

	// 增加对AspectJ的支持
	if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
		beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
		beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
	}

	// 注册4个默认的系统环境bean
	if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) // environment
		beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
	if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) // systemProperties
		beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
	if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) // systemEnvironment
		beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
	if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) // applicationStartup
		beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}

4.2> 添加对SpEL表达式的支持

SpEL全称是“Spring Expression Language”,它能在运行时构件复杂表达式存取对象图属性对象方法调用等;它是单独模块,只依赖了core模块,所以可以单独使用。SpEL使用 #{...} 作为界定符,所有在大括号中的字符都会被认定为SpEL,使用方式如下所示:

<bean id="user" value="com.muse.entity.User"/>
<bean ...>
    <property name="name" value="#{user}">
</bean>
    
相当于:
    
<bean id="user" value="com.muse.entity.User"/>
<bean ...>
    <property name="name" ref="user">
</bean>

prepareBeanFactory(beanFactory) 方法中,通过beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(...))注册SpEL语言解析器,就可以对SpEL进行解析了。

那么,在注册了解析器后,**Spring又是在什么时候调用这个解析器进行解析操作的呢?**调用方式如下图所示:

(五)Spring源码解析:ApplicationContext源码解析

解释】其实就是在Spring进行bean初始化的时候,有一个步骤是——属性填充(即:populateBean()),而在这一步中Spring会调用AbstractAutowireCapableBeanFactory#applyPropertyValues(...)方法来完成功能。而就在这个方法中,会创建BeanDefinitionValueResolver实例对象valueResolver来进行属性值的解析操作。同时,也是在这个步骤中,通过AbstractBeanFactory#evaluateBeanDefinitionString(...)方法去完成SpEL的解析操作

相关源码如下所示:

protected Object evaluateBeanDefinitionString(String value, BeanDefinition beanDefinition) {
	if (this.beanExpressionResolver == null) return value;
	Scope scope = null;
	if (beanDefinition != null) {
		String scopeName = beanDefinition.getScope();
		if (scopeName != null) scope = getRegisteredScope(scopeName);
	}
    // 通过获得的beanExpressionResolver实例调用evaluate(...)方法执行解析操作
	return this.beanExpressionResolver.evaluate(value, new BeanExpressionContext(this, scope));
}

4.3> 添加属性编辑器

下面我们继续来介绍一下beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));这行代码,那么通过调用的方法名称,我们可以猜到它的作用是给BeanFactory实例添加属性编辑器。那么,什么是属性编辑器呢? 在Spring加载bean的时候,可以把基本类型属性注入进来,但是对于类似Date这种复杂属性就无法被识别了。

4.3.1> 属性编辑器的应用

我们假设有一个Schedule类,其中包含了一个Date类型的属性,如果采用默认加载方式的话,是无法将xml中配置的"2023-01-01"值转换为Date类型的。那么,下面我们就来演示一下如何通过自定义属性编辑器来让Spring在加载bean的时候,将String类型的值转换为Date类型的值。如下所示:

@Data
public class Schedule {
    private String name;
    private Date date; // 添加Date类型的属性
}
<bean id="schedule" class="com.muse.springbootdemo.entity.propertyeditor.Schedule">
  <property name="name" value="work"/>
  <property name="date" value="2023-01-01"/> <!-- date是Date类型,需要将String转换为Date -->
</bean>

当我们运行的时候发现报错了,即:无法将配置文件中的String类型转换为Date类型

(五)Spring源码解析:ApplicationContext源码解析

那么,我们添加用来将String类型转换为Date类型的属性编译器DatePropertyEditor,并将其注入到CustomEditorConfigurer中即可。

public class DatePropertyEditor implements PropertyEditorRegistrar {
    @Override
    public void registerCustomEditors(PropertyEditorRegistry registry) {
        registry.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
    }
}
<!-- 注册属性编辑器 -->
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
    <property name="propertyEditorRegistrars"> <!-- 将自定义属性编辑器保存到propertyEditorRegistrars属性中 -->
        <list>
            <bean class="com.muse.springbootdemo.entity.propertyeditor.DatePropertyEditor"/>
        </list>
    </property>
</bean>

(五)Spring源码解析:ApplicationContext源码解析

在调用registerCustomEditor(...)方法的时候,我们创建了CustomDateEditor实例对象,在此处我们只是来看一下它的类继承关系,下文还会涉及对它的介绍。

(五)Spring源码解析:ApplicationContext源码解析

4.3.2> 源码解析

通过上面对于注册属性编辑器的配置,我们可以看到自定义的属性编辑器DatePropertyEditor被保存到了CustomEditorConfigurerpropertyEditorRegistrars属性中,那么由于CustomEditorConfigurer类实现了BeanFactoryPostProcessor接口,所以当bean初始化的时候,会调用它的postProcessBeanFactory(...)方法,那么在这个方法中,会将propertyEditorRegistrars属性中的所有属性编辑器添加到beanFactory中。

(五)Spring源码解析:ApplicationContext源码解析

那么,我们在回头来看 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())) 的这行代码,其实也是同样的调用方式:

(五)Spring源码解析:ApplicationContext源码解析

那么,我们分析到这一步之后,发现自定义属性编辑器都会保存到ConfigurableListableBeanFactory实例对象beanFactory的变量propertyEditorRegistrars中。那么问题来了——保存我们知道了,那什么时候属性编辑器会被调用呢? 其实就是在初始化bean的时候,在initBeanWrapper(...)方法中,会被调用。

(五)Spring源码解析:ApplicationContext源码解析

那么综上所述,我们来通过一张图,了解一下属性编辑器的注册和使用操作相关的类关系图:

(五)Spring源码解析:ApplicationContext源码解析

在上面的例子中,我们自定义了一个属性编辑器DatePropertyEditor,其实Spring也内置了自己的属性编辑器ResourceEditorRegistrar

(五)Spring源码解析:ApplicationContext源码解析

ResourceEditorRegistrarregisterCustomEditors(...)方法中,提供了Spring默认配置的所有属性编辑器集合。如下所示:

(五)Spring源码解析:ApplicationContext源码解析

doRegisterEditor(...)中,我们发现该方法的内部实现与自定义属性编辑器实现方式基本一样,即:通过调用registry.registerCustomEditor(requiredType, editor)方法来注册属性编辑器。如下所示:

(五)Spring源码解析:ApplicationContext源码解析

此处我们再提及一点,就是在PropertyEditorRegistrySupport类的createDefaultEditors()方法中,包含了Spring给我们提供的一系列默认编辑器。具体如下所示:

private void createDefaultEditors() {
	this.defaultEditors = new HashMap<>(64);
    
    // Simple editors, without parameterization capabilities.
	this.defaultEditors.put(Charset.class, new CharsetEditor());
	this.defaultEditors.put(Class.class, new ClassEditor());
	this.defaultEditors.put(Class[].class, new ClassArrayEditor());
	this.defaultEditors.put(Currency.class, new CurrencyEditor());
	this.defaultEditors.put(File.class, new FileEditor());
	this.defaultEditors.put(InputStream.class, new InputStreamEditor());
	if (!shouldIgnoreXml) 
		this.defaultEditors.put(InputSource.class, new InputSourceEditor());
	this.defaultEditors.put(Locale.class, new LocaleEditor());
	this.defaultEditors.put(Path.class, new PathEditor());
	this.defaultEditors.put(Pattern.class, new PatternEditor());
	this.defaultEditors.put(Properties.class, new PropertiesEditor());
	this.defaultEditors.put(Reader.class, new ReaderEditor());
	this.defaultEditors.put(Resource[].class, new ResourceArrayPropertyEditor());
	this.defaultEditors.put(TimeZone.class, new TimeZoneEditor());
	this.defaultEditors.put(URI.class, new URIEditor());
	this.defaultEditors.put(URL.class, new URLEditor());
	this.defaultEditors.put(UUID.class, new UUIDEditor());
	this.defaultEditors.put(ZoneId.class, new ZoneIdEditor());
    
	// Default instances of collection editors.
	this.defaultEditors.put(Collection.class, new CustomCollectionEditor(Collection.class));
	this.defaultEditors.put(Set.class, new CustomCollectionEditor(Set.class));
	this.defaultEditors.put(SortedSet.class, new CustomCollectionEditor(SortedSet.class));
	this.defaultEditors.put(List.class, new CustomCollectionEditor(List.class));
	this.defaultEditors.put(SortedMap.class, new CustomMapEditor(SortedMap.class));
    
	// Default editors for primitive arrays.
	this.defaultEditors.put(byte[].class, new ByteArrayPropertyEditor());
	this.defaultEditors.put(char[].class, new CharArrayPropertyEditor());
    
	// The JDK does not contain a default editor for char!
	this.defaultEditors.put(char.class, new CharacterEditor(false));
	this.defaultEditors.put(Character.class, new CharacterEditor(true));
    
	// Spring's CustomBooleanEditor accepts more flag values than the JDK's default editor.
	this.defaultEditors.put(boolean.class, new CustomBooleanEditor(false));
	this.defaultEditors.put(Boolean.class, new CustomBooleanEditor(true));
    
	// The JDK does not contain default editors for number wrapper types!
	// Override JDK primitive number editors with our own CustomNumberEditor.
	this.defaultEditors.put(byte.class, new CustomNumberEditor(Byte.class, false));
	this.defaultEditors.put(Byte.class, new CustomNumberEditor(Byte.class, true));
	this.defaultEditors.put(short.class, new CustomNumberEditor(Short.class, false));
	this.defaultEditors.put(Short.class, new CustomNumberEditor(Short.class, true));
	this.defaultEditors.put(int.class, new CustomNumberEditor(Integer.class, false));
	this.defaultEditors.put(Integer.class, new CustomNumberEditor(Integer.class, true));
	this.defaultEditors.put(long.class, new CustomNumberEditor(Long.class, false));
	this.defaultEditors.put(Long.class, new CustomNumberEditor(Long.class, true));
	this.defaultEditors.put(float.class, new CustomNumberEditor(Float.class, false));
	this.defaultEditors.put(Float.class, new CustomNumberEditor(Float.class, true));
	this.defaultEditors.put(double.class, new CustomNumberEditor(Double.class, false));
	this.defaultEditors.put(Double.class, new CustomNumberEditor(Double.class, true));
	this.defaultEditors.put(BigDecimal.class, new CustomNumberEditor(BigDecimal.class, true));
	this.defaultEditors.put(BigInteger.class, new CustomNumberEditor(BigInteger.class, true));
    
	// Only register config value editors if explicitly requested.
	if (this.configValueEditorsActive) {
		StringArrayPropertyEditor sae = new StringArrayPropertyEditor();
		this.defaultEditors.put(String[].class, sae);
		this.defaultEditors.put(short[].class, sae);
		this.defaultEditors.put(int[].class, sae);
		this.defaultEditors.put(long[].class, sae);
	}
}

4.4> 添加ApplicationContextAwareProcessor处理器

下面我们继续来分析prepareBeanFactory(...)方法中的源码,如下所示:

(五)Spring源码解析:ApplicationContext源码解析

解释】在上面的源码红框中,只是将ApplicationContextAwareProcessor实例对象添加到了beanFactory的后置处理器集合中(即:List<BeanPostProcessor> beanPostProcessors)。

那既然ApplicationContextAwareProcessor是后置处理器,那它必然就已经实现了BeanPostProcessor接口。那么问题来了,后置处理器会在什么时候被Spring调用呢? 这个问题在前面章节的 bean实例化 过程中其实已经介绍过了,我们再来回顾一下。请见下图所示:

(五)Spring源码解析:ApplicationContext源码解析

解释】在bean实例化的时候,也就是在Spring调用init-method方法的前后,会分别调用所有实现了BeanPostProcessor接口的实现类的postProcessBeforeInitialization(...)方法和postProcessAfterInitialization(...)方法。那么,下面我们就来看一下ApplicationContextAwareProcessor是如何自定义这两个方法的具体逻辑的。

ApplicationContextAwareProcessorpostProcessAfterInitialization(...)方法没有做特殊逻辑处理,采用的就是它父接口BeanPostProcessor中默认的方法实现。源码如下所示:

default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
	return bean;
}

ApplicationContextAwareProcessorpostProcessBeforeInitialization(...)方法做了自定义的实现,源码如下所示:

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    // 只针对如下7种xxxAware进行特殊处理
	if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
			bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
			bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
			bean instanceof ApplicationStartupAware)) return bean;
	... ...
    invokeAwareInterfaces(bean); // 为7种xxxAware设置对应的资源
	... ...
	return bean;
}
private void invokeAwareInterfaces(Object bean) {
	if (bean instanceof EnvironmentAware) 
		((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
	if (bean instanceof EmbeddedValueResolverAware) 
		((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
	if (bean instanceof ResourceLoaderAware) 
		((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
	if (bean instanceof ApplicationEventPublisherAware) 
		((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
	if (bean instanceof MessageSourceAware) 
		((MessageSourceAware) bean).setMessageSource(this.applicationContext);
	if (bean instanceof ApplicationStartupAware) 
		((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
	if (bean instanceof ApplicationContextAware) 
		((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}

解释】通过上面的源码,我们可以发现,在后置处理方法中,只是针对7种Aware实现设置了它们所需的资源。

4.5> 设置忽略依赖

我们继续来分析prepareBeanFactory(...)方法中如下红框的内容。在4.3中我们当通过调用ApplicationContextAwareProcessor类的invokeAwareInterfaces()方法之后,7种xxxAware类型bean就都已经处理完毕了,那么下面的依赖注入操作就不需要再处理这些xxxAware类了。所以在如下红框种就对这7种Aware类执行了忽略依赖操作。

(五)Spring源码解析:ApplicationContext源码解析

4.6> 注册依赖

下面我们再来继续分析prepareBeanFactory(...)方法中如下红框的内容。这部分内容是,当注册了依赖解析后,例如当注册了对BeanFactory.class的解析依赖后,当bean的属性注入的时候,一旦检测到属性为BeanFactory类型便会将beanFactory的实例注入进去。

(五)Spring源码解析:ApplicationContext源码解析

五、invokeBeanFactoryPostProcessors(...)激活各种BeanFactory的后置处理器

下面我们来分析refresh()方法中的invokeBeanFactoryPostProcessors(beanFactory)这段代码的含义之前,通过方法名称,我们可以猜到这段方法是用来处理BeanFactoryPostProcessor的,那么 它具体是做什么的呢? 请见如下源码所示:

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

解释BeanFactoryPostProcessor接口跟BeanPostProcessor类似,都可以对bean的定义(即:配置的元数据)进行处理。也就是说,**Spring允许BeanFactoryPostProcessor在容器实际实例化任何其他的bean之前读取配置元数据,并进行修改。**如果配置多个BeanFactoryPostProcessor,可以通过实现Ordered接口来控制执行次序。

如果你想改变实际的bean实例,那么最好使用BeanPostProcessor。因为BeanFactoryPostProcessor的作用域范围是容器级别的。它只和你所使用的容器有关。它不会对定义在另一个容器中的bean进行后置处理。

那么,我们先不着急解析invokeBeanFactoryPostProcessors(beanFactory)这段源码的具体逻辑,我们先插播一条“娱乐新闻”,即:如何去使用BeanFactoryPostProcessor

5.1> PropertySourcesPlaceholderConfigurer�的应用

在某个路径下创建一个配置文件,我们以prop/common.properties为例,在该文件内配置相应的属性值。

(五)Spring源码解析:ApplicationContext源码解析

然后创建message的Bean配置信息,变量引用:${message.msg}。表明在其他的配置文件中指定了message.msg的值。那到底是哪个配置文件呢?我们创建PropertySourcesPlaceholderConfigurer的Bean配置信息。通过locations属性,来指定配置文件所在路径。

(五)Spring源码解析:ApplicationContext源码解析

从IOC中获取message的bean实例对象,然后输出msg的值。

(五)Spring源码解析:ApplicationContext源码解析

在上面的演示中,我们可以看到虽然在配置PropertySourcesPlaceholderConfigurer的Bean时指定了common.properties的文件路径,但是这个文件是什么时候被加载解析的呢? 答案是:PropertySourcesPlaceholderConfigurer其实就是一种BeanFactoryPostProcessor,那么当Spring加载任何实现了这个接口的bean的配置时,都会在bean工厂载入所有bean的配置之后执行postProcessBeanFactory(beanFactory)方法。类的继承关系图请见下图所示:

(五)Spring源码解析:ApplicationContext源码解析

本节开篇就说了,BeanFactoryPostProcessor接口只有一个方法,即:postProcessBeanFactory(beanFactory),那么下面我们来看一下PropertySourcesPlaceholderConfigurer类是怎么实现的这个方法:

(五)Spring源码解析:ApplicationContext源码解析

(五)Spring源码解析:ApplicationContext源码解析

那么当配置文件信息被加载到了内存中后,就可以通过message.msg所配置的“Hello World!”值来替换${message.msg}了。此处替换流程暂且不深究。下面我们来看看如何自己实现一个BeanFactoryPostProcessor。

5.2> 自定义BeanFactoryPostProcessor的应用

实现接口BeanFactoryPostProcessor,创建自定义处理类。在postProcessBeanFactory�(beanFactory)方法中实现垃圾话过滤逻辑。需要注意的是,这个过滤垃圾话的作用域是针对容器内所有的bean的

(五)Spring源码解析:ApplicationContext源码解析

配置Bean,设置需要过滤的垃圾话列表。

(五)Spring源码解析:ApplicationContext源码解析

获取allMessage的bean实例,验证msg中的垃圾话是否被过滤掉了。

(五)Spring源码解析:ApplicationContext源码解析

5.3> 激活BeanFactoryPostProcessor源码解析

5.3.1> 源码注释解析

通过上面的示例,我们基本了解到了BeanFactoryPostProcessor是如何使用的。那么,下面我们还是回到refresh()方法中,看一下invokeBeanFactoryPostProcessors(beanFactory)这段代码的具体实现逻辑:

(五)Spring源码解析:ApplicationContext源码解析

invokeBeanFactoryPostProcessors(beanFactory)方法的源码如下所示:

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // 激活BeanFactoryPostProcessor操作
	PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
	
	if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null 
        && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
		beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
		beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
	}
}

激活的实际逻辑代码就在invokeBeanFactoryPostProcessors(...)方法中,里面逻辑很多,我们先看这个方法的源码和注释,然后我们在下面内容中,抽取重要的内容再详细的讨论。

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, 
                                                 List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
	Set<String> processedBeans = new HashSet<>(); // 用于存储已经处理过的处理器名称
    
    /** 步骤1:对BeanDefinitionRegistry类型进行处理,包括【硬编码】+【配置方式】 */
	if (beanFactory instanceof BeanDefinitionRegistry) {
		BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; 
		List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(); // 通过【硬编码】注册的BeanFactoryPostProcessor
		List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); // 通过【硬编码】注册的BeanDefinitionRegistryPostProcessor

        /** 步骤1.1:遍历所有通过【硬编码】设置的BeanFactoryPostProcessor,按类型执行“分堆”操作,调用其postProcessBeanDefinitionRegistry(registry)方法 */
		for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
			if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { 
				BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor;
                registryProcessor.postProcessBeanDefinitionRegistry(registry); // BeanDefinitionRegistryPostProcessor接口中的方法,对BeanDefinitionRegistry执行后置处理
				registryProcessors.add(registryProcessor); // 通过【硬编码】注册的BeanDefinitionRegistryPostProcessor,会被放到registryProcessors中
			} else {
				regularPostProcessors.add(postProcessor); // 通过【硬编码】注册的其它BeanFactoryPostProcessor,会被放到regularPostProcessors中
			}
		}

        /** 步骤1.2:处理所有通过【配置方式】注册且实现了”PriorityOrdered接口“的BeanDefinitionRegistryPostProcessor实例集合,调用其postProcessBeanDefinitionRegistry(registry)方法 */
		List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
		for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { // 如果实现了PriorityOrdered接口,则进行排序
				currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
				processedBeans.add(ppName);
			}
		}
		sortPostProcessors(currentRegistryProcessors, beanFactory); // 排序
		registryProcessors.addAll(currentRegistryProcessors); // 合并【硬编码】和【配置方式(且实现了PriorityOrdered接口)】的BeanDefinitionRegistryPostProcessor集合
		// 调用所有currentRegistryProcessors实例的postProcessBeanDefinitionRegistry(registry)方法,实现对registry的后置处理
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
		currentRegistryProcessors.clear();

        /** 步骤1.3:处理所有通过【配置方式】注册且实现了”Ordered接口“的BeanDefinitionRegistryPostProcessor实例集合,调用其postProcessBeanDefinitionRegistry(registry)方法 */
		postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
		for (String ppName : postProcessorNames) {
			if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { // 如果实现了Ordered接口,则进行排序
				currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
				processedBeans.add(ppName);
			}
		}
		sortPostProcessors(currentRegistryProcessors, beanFactory); // 排序
		registryProcessors.addAll(currentRegistryProcessors); // 合并【硬编码】和【配置方式(且实现了Ordered接口)】的BeanDefinitionRegistryPostProcessor集合
		invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
		currentRegistryProcessors.clear();

        /** 步骤1.4:处理所有通过【配置方式】注册且实现了BeanDefinitionRegistryPostProcessor实例集合(排除实现Ordered接口和PriorityOrdered接口),调用其postProcessBeanDefinitionRegistry(registry)方法 */
		boolean reiterate = true;
		while (reiterate) {
			reiterate = false;
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (!processedBeans.contains(ppName)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
					reiterate = true;
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
			currentRegistryProcessors.clear();
		}

        /** 步骤1.5:处理BeanDefinitionRegistryPostProcessor实例集合和BeanFactoryPostProcessor实例集合,调用其postProcessBeanFactory(beanFactory)方法 */
		invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
	}
        
    /** 步骤2:对ConfigurableListableBeanFactory而非BeanDefinitionRegistry类型进行处理【硬编码】+【配置方式】 ,调用其postProcessBeanFactory(beanFactory)方法*/
	else {
		invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
	}

	String[] postProcessorNames =
			beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
	List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
	List<String> orderedPostProcessorNames = new ArrayList<>();
	List<String> nonOrderedPostProcessorNames = new ArrayList<>();
	for (String ppName : postProcessorNames) {
		if (processedBeans.contains(ppName)) // skip - already processed in first phase above
		else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) // 如果实现了PriorityOrdered接口,则进行排序
			priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
		else if (beanFactory.isTypeMatch(ppName, Ordered.class)) // 如果实现了Ordered接口,则进行排序
			orderedPostProcessorNames.add(ppName);
		else 
			nonOrderedPostProcessorNames.add(ppName); // 否则,不排序了
	}

    /** 步骤3:对ConfigurableListableBeanFactory类型并且实现了”PriorityOrdered接口“的进行处理【配置方式】 ,调用其postProcessBeanFactory(beanFactory)方法*/
	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
	invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
	for (String postProcessorName : orderedPostProcessorNames) {
		orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
	}

    /** 步骤4:对ConfigurableListableBeanFactory类型并且实现了”Ordered接口“的进行处理【配置方式】 ,调用其postProcessBeanFactory(beanFactory)方法*/
	sortPostProcessors(orderedPostProcessors, beanFactory);
	invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
	for (String postProcessorName : nonOrderedPostProcessorNames) {
		nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
	}

    /** 步骤5:对ConfigurableListableBeanFactory类型并且没有实现(PriorityOrdered接口或Ordered接口)进行处理【配置方式】 ,调用其postProcessBeanFactory(beanFactory)方法*/
	invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
	beanFactory.clearMetadataCache();
}

通过上面的源码和源码注释,我们可以看到,其实就是针对两种情况进行分别的后置处理:

情况1】一个类实现了ConfigurableListableBeanFactory接口 + BeanDefinitionRegistry接口 【情况2】一个类仅实现了ConfigurableListableBeanFactory接口

而对于后置处理器来说,有如下对应的处理关系:

针对BeanDefinitionRegistry接口】我们采用BeanDefinitionRegistryPostProcessor后置处理器进行增强操作。 【针对ConfigurableListableBeanFactory接口】我们采用BeanFactoryPostProcessor后置处理器进行增强操作。

而由于BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor,所以要区别处理:

(五)Spring源码解析:ApplicationContext源码解析

5.3.2> 整体流程概述

找出实现了BeanDefinitionRegistry接口 + ConfigurableListableBeanFactory接口的bean

步骤1】调用“硬编码”设置的BeanDefinitionRegistryPostProcessorpostProcessBeanDefinitionRegistry(registry)方法进行增强; 【步骤2】调用“配置方式”设置的BeanDefinitionRegistryPostProcessor并实现了PriorityOrdered接口的postProcessBeanDefinitionRegistry(registry)方法进行增强; 【步骤3】调用“配置方式”设置的BeanDefinitionRegistryPostProcessor并实现了Ordered接口的postProcessBeanDefinitionRegistry(registry)方法进行增强; 【步骤4】调用“配置方式”设置的BeanDefinitionRegistryPostProcessor没有实现排序接口的postProcessBeanDefinitionRegistry(registry)方法进行增强; 【步骤5】调用“硬编码BeanDefinitionRegistryPostProcessorpostProcessBeanFactory(beanFactory)方法进行增强; 【步骤6】调用“硬编码BeanFactoryPostProcessorpostProcessBeanFactory(beanFactory)方法进行增强;

找出仅仅实现了ConfigurableListableBeanFactory接口的bean

步骤1】调用“硬编码”设置BeanFactoryPostProcessorpostProcessBeanFactory(beanFactory)方法进行增强; 【步骤2】调用“配置方式”设置的BeanFactoryPostProcessor并实现了PriorityOrdered接口的postProcessBeanFactory(beanFactory)方法进行增强; 【步骤3】调用“配置方式”设置的BeanFactoryPostProcessor并实现了Ordered接口的postProcessBeanFactory(beanFactory)方法进行增强; 【步骤4】调用“配置方式”设置的BeanFactoryPostProcessor没有实现排序接口的postProcessBeanFactory(beanFactory)方法进行增强;

那么,什么样的类即实现BeanDefinitionRegistry接口又实现ConfigurableListableBeanFactory接口呢? 我们以DefaultListableBeanFactory为例,它就是既实现了ConfigurableListableBeanFactory接口,也实现了BeanDefinitionRegistry接口。如下所示:

(五)Spring源码解析:ApplicationContext源码解析

那么 上面所说的【硬编码】,又是从哪里写入的呢? 我们可以看到在 AbstractApplicationContext 类中有addBeanFactoryPostProcessor(postProcessor)方法,通过它,我们就可以采用硬编码的方式添加PostProcessor了。

(五)Spring源码解析:ApplicationContext源码解析

为了更便于大家对整个流程的理解,如下我提供了针对整体处理流程的图解。

5.3.3> 整体流程图解

针对实现了BeanDefinitionRegistry接口 + ConfigurableListableBeanFactory接口 的bean,调用BeanDefinitionRegistryPostProcessor 类的postProcessBeanDefinitionRegistry�(registry)方法的后置处理

(五)Spring源码解析:ApplicationContext源码解析

针对实现了BeanDefinitionRegistry接口 + ConfigurableListableBeanFactory接口 的bean,调用 BeanFactoryPostProcessor 类的postProcessBeanFactory(beanFactory)方法的后置处理

(五)Spring源码解析:ApplicationContext源码解析

针对仅仅实现了ConfigurableListableBeanFactory接口的bean,调用BeanFactoryPostProcessor类的postProcessBeanFactory(beanFactory)方法的后置处理

(五)Spring源码解析:ApplicationContext源码解析

六、registerBeanPostProcessors(...)注册各种Bean的后置处理器

6.1> 使用示例

创建一个BeanPostProcessor的实现类——MuseBeanPostProcessor.java

(五)Spring源码解析:ApplicationContext源码解析

oldbean.xml配置文件中注册MuseBeanPostProcessor后置处理器。

(五)Spring源码解析:ApplicationContext源码解析

启动项目,我们发现当使用ApplicationContext加载bean的时候,就可以调用我们创建的后置处理器;但是如果使用XmlBeanFactory加载bean,却无法调用我们创建的后置处理器

(五)Spring源码解析:ApplicationContext源码解析

其实这也印证了ApplicationContext是BeanFactory的加强版本,即:Plus版本。在Spring中,其实绝大部分的功能都是通过后置处理器的方式进行扩展的,而BeanFactory其实只是初始化IOC容器了,并没有实现后置处理器的自动注册功能。

而ApplicationContext实现了自动添加后置处理器的能力,所以才会通过调用applicationContext.getBean("allMessage")的方式输出了“-------allMessage---------”,而通过beanFactory.getBean("allMessage")的方式却没有输出。

6.2> 源码解析

我们了解了怎样去使用BeanPostProcessor之后,下面我们来看一下涉及到注册BeanPostProcessor的逻辑代码,如下所示:

(五)Spring源码解析:ApplicationContext源码解析

如下是最核心的BeanPostProcessor方法,这里面的逻辑与BeanFactoryPostProcessor类似,请见如下源码和注释:

public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
	String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
	
    // BeanPostProcessorChecker是一个用于检查操作的后置处理器,即:当Spring配置中的后处理器还没有被注册就已经开始了bean的初始化是,那么Checker就会打印提示信息日志
    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)) { // 存储实现了PriorityOrdered接口的后置处理器
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); 
			priorityOrderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) 
				internalPostProcessors.add(pp); // 存储实现了PriorityOrdered接口并且是MergedBeanDefinitionPostProcessor类型后置处理器
		}
		else if (beanFactory.isTypeMatch(ppName, Ordered.class)) 
			orderedPostProcessorNames.add(ppName); // 存储实现了Ordered接口的后置处理器
		else 
			nonOrderedPostProcessorNames.add(ppName); // 存储未实现排序接口的后置处理器
	}
	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
	registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
	
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
	for (String ppName : orderedPostProcessorNames) {
		BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
		orderedPostProcessors.add(pp);
		if (pp instanceof MergedBeanDefinitionPostProcessor) {
			internalPostProcessors.add(pp); // 存储实现了Ordered接口并且是MergedBeanDefinitionPostProcessor类型后置处理器
		}
	}
	sortPostProcessors(orderedPostProcessors, beanFactory);
	registerBeanPostProcessors(beanFactory, orderedPostProcessors);

    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
	for (String ppName : nonOrderedPostProcessorNames) {
		BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
		nonOrderedPostProcessors.add(pp);
		if (pp instanceof MergedBeanDefinitionPostProcessor) {
			internalPostProcessors.add(pp); // 存储没有实现排序接口并且是MergedBeanDefinitionPostProcessor类型后置处理器
		}
	}
	registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

    // 注册MergedBeanDefinitionPostProcessor类型后置处理器
	sortPostProcessors(internalPostProcessors, beanFactory);
	registerBeanPostProcessors(beanFactory, internalPostProcessors);
    
	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

步骤1】针对实现了PriorityOrdered接口的BeanPostProcessor后置处理器执行排序和注册操作。 【步骤2】针对实现了Ordered接口的BeanPostProcessor后置处理器执行排序和注册操作。 【步骤3】针对没有实现排序接口的BeanPostProcessor后置处理器执行注册操作。 【步骤4】针对MergedBeanDefinitionPostProcessor类型的后置处理器执行注册操作。

在调用registerBeanPostProcessors(...)方法时,不用担心重复注册问题,因为都是先执行remove再执行add的,如下所示:

(五)Spring源码解析:ApplicationContext源码解析

七、initMessageSource()为上下文初始化消息源

Spring国际化是根据客户端的系统语言类型返回对应的界面,这个便是所谓的i18n国际化(internationalization)。

国际化信息也称之为本地化信息,需要两个条件来最终决定:

条件1】语言类型(eg:中文) 【条件2】国家/地区的类型(ge:中国大陆、中国台湾、中国香港、新加坡、马来西亚……)

在JDK中,提供了java.util.Locale类用来支持国际化信息,它提供了如下使用方式:

方式1】指定语言和国家/地区——new Locale("zh", "CN")Locale.CHINA方式2】指定语言——new Locale("zh")Locale.CHINESE方式3】根据操作系统默认语言设置——Locale.getDefault()

MessageSource是负责国际化信息的接口,它有如下几个重要实现类:

ResourceBundleMessageSource:允许通过资源名加载国际化资源。 ReloadableResourceBundleMessageSource:与ResourceBundleMessageSource功能相似,额外提供定时刷新功能,不用重启系统,即可更新资源信息。 StaticMessageSource:主要用于程序测试,允许通过编程的方式提供国际化信息。 DelegatingMessageSource:为方便操作MessageSource的代理类。

7.1> 使用示例

创建i18n_zh.properties文件,里面添加“hello=你好!世界!”,然后通过 native2ascii 将其转化为utf8的ASCII编码文件。

(五)Spring源码解析:ApplicationContext源码解析

创建i18n_en.properties文件,里面添加“hello=Hello World!”,然后将i18n_zh.propertiesi18n_en.properties都放入到muse文件夹下。如下所示:

(五)Spring源码解析:ApplicationContext源码解析

在配置文件oldbean.xml中配置国际化支持,其中bean id必须是“messageSource”,否则就会报NoSuchMessageException异常

(五)Spring源码解析:ApplicationContext源码解析

执行测试代码:

(五)Spring源码解析:ApplicationContext源码解析

7.2> 源码解析

了解了怎么使用国际化信息之后,我们现在来看一下初始化国际化资源的代码逻辑,如下图红框所示:

(五)Spring源码解析:ApplicationContext源码解析

那么,在initMessageSource()方法中,通过判断是自定义国际化资源还是默认国际化资源,创建MessageSource实现类,然后赋值给AbstractApplicationContext的全局变量messageSource

protected void initMessageSource() {
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 如果需要用户自定义国际化资源,则需要创建一个bean的id必须是“messageSource”(硬编码)的bean
	if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) { 
		this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class); // 赋值给全局变量messageSource
		if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
			HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
			if (hms.getParentMessageSource() == null) {
				hms.setParentMessageSource(getInternalParentMessageSource());
			}
		}
	}
	// 否则,使用DelegatingMessageSource,一般后续通过调用getMessage方法返回国际化资源
	else {
		DelegatingMessageSource dms = new DelegatingMessageSource();
		dms.setParentMessageSource(getInternalParentMessageSource());
		this.messageSource = dms; // 赋值给全局变量messageSource
		beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
	}
}

protected MessageSource getInternalParentMessageSource() {
	return (getParent() instanceof AbstractApplicationContext ?
        ((AbstractApplicationContext) getParent()).messageSource : getParent());
}

public ApplicationContext getParent() {
	return this.parent;
}

在使用时,我们通过调用applicationContext.getMessage("hello", null, Locale.US)来获取国际化信息,那么我们看一下getMessage(...)方法的源码是怎么处理的:

public String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException {
	return getMessageSource().getMessage(code, args, locale);
}

private MessageSource getMessageSource() throws IllegalStateException {
	if (this.messageSource == null) 
		throw new IllegalStateException("MessageSource not initialized - call 'refresh' before accessing messages via the context: " + this);
	return this.messageSource; // 就是从全局messageSource中获取的国际化资源
}

八、initApplicationEventMulticaster()为上下文初始化应用事件广播器

8.1> 使用示例

首先,继承ApplicationEvent,实现自定义ApplicationEvent——MuseApplicationEvent

(五)Spring源码解析:ApplicationContext源码解析

其次,实现ApplicationListener接口,实现自定义ApplicationListener——MuseApplicationListener

(五)Spring源码解析:ApplicationContext源码解析

将自定义应用监听器MuseApplicationListener注册倒IOC中:

(五)Spring源码解析:ApplicationContext源码解析

测试发布一个MuseApplicationEvent类型的事件,查看控制台输出内容:

(五)Spring源码解析:ApplicationContext源码解析

8.2> 源码解析

好了,我们通过刚刚的示例,了解到了如何使用应用事件发起广播,那么下面我们就来看一下源码中如何进行初始化操作的,在下图refresh()方法的红框中:

(五)Spring源码解析:ApplicationContext源码解析

我们再来看initApplicationEventMulticaster()方法的具体处理逻辑:

protected void initApplicationEventMulticaster() {
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 如果用户【自定义】了EventMulticaster,则向Spring中注册用户自定义的事件广播器
	if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
		this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
	}
    // 如果用户【没有自定义】EventMulticaster,则向Spring中注册默认的SimpleApplicationEventMulticaster广播器
	else {
		this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
		beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
	}
}

上面的代码逻辑也是比较简单清晰的,就执行了两个判断逻辑: 【判断1】如果用户自定义了EventMulticaster,则向Spring中注册用户自定义的事件广播器。 【判断2】如果用户没有自定义EventMulticaster,则向Spring中注册默认的SimpleApplicationEventMulticaster广播器

那么,我们在看一下SimpleApplicationEventMulticaster中是怎么处理广播事件的:

public void multicastEvent(ApplicationEvent event) {
	multicastEvent(event, resolveDefaultEventType(event));
}
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
	ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
	Executor executor = getTaskExecutor();
	for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
		if (executor != null) 
			executor.execute(() -> invokeListener(listener, event)); // 采用并行方式执行广播操作
		else 
			invokeListener(listener, event); // 采用串行方式执行广播操作
	}
}

protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
	ErrorHandler errorHandler = getErrorHandler();
	if (errorHandler != null) 
		try {
			doInvokeListener(listener, event); // 触发广播监听行为
		}catch (Throwable err) {errorHandler.handleError(err);}
	else 
		doInvokeListener(listener, event); // 触发广播监听行为
}

private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
	try {
		listener.onApplicationEvent(event); // 发送监听事件
	}catch (ClassCastException ex) {...}
}

从上面的代码中,我们可以看出核心的逻辑就是两个步骤: 【步骤1】通过getApplicationListeners(event, type)方法获得所有的应用监听器列表。 【步骤2】遍历调用每一个ApplicationListeneronApplicationEvent(event)方法来发送监听事件。

需要注意的一点就是,当产生Spring监听事件的时候,对于每一个监听器来说,其实他们都可以获得所有产生的监听事件,那么具体处理哪一种类型的监听事件,可以在监听器中进行逻辑处理(如:上面8.1使用示例中的MuseApplicationListener实现方式)。当然,我们也可以通过使用泛型来约束处理的监听事件类型。如下图所示,那么MuseApplicationListener就只能处理MuseApplicationEvent类型的事件了。

(五)Spring源码解析:ApplicationContext源码解析

九、registerListeners()注册监听器

注册监听器的理解代码如下所示:

(五)Spring源码解析:ApplicationContext源码解析

下面我们再来详细看一下registerListeners()方法的具体逻辑:

protected void registerListeners() {
    /** 添加以【硬编码】方式注册的监听器 */
    for (ApplicationListener<?> listener : getApplicationListeners()) 
    	getApplicationEventMulticaster().addApplicationListener(listener);

	/** 添加以【配置文件】方式注册的监听器 */
	String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
	for (String listenerBeanName : listenerBeanNames) 
	    getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    
	/** 发送在多播设置之前发布的ApplicationEvent事件 */
	Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
	this.earlyApplicationEvents = null;
	if (!CollectionUtils.isEmpty(earlyEventsToProcess)) 
	    for (ApplicationEvent earlyEvent : earlyEventsToProcess) 
	        getApplicationEventMulticaster().multicastEvent(earlyEvent);
}

注册监听器的方法也比较简单清晰,它一共做到了如下3个步骤: 【步骤1】添加以硬编码方式注册的监听器 【步骤2】添加以配置文件方式注册的监听器 【步骤3】发送在多播设置之前发布的ApplicationEvent事件

十、finishBeanFactoryInitialization(...)初始化非延迟加载单例

10.1> 概述

此处涉及到的就是我们完成了BeanFactory初始化工作之后的收尾工作了,包含:

步骤1】为上下文添加ConversionService 【步骤2】为上下文添加EmbeddedValueResolver(嵌入值解析器) 【步骤3】初始化LoadTimeWeaverware类型的Bean 【步骤4】停止使用临时ClassLoader进行类型匹配 【步骤5】冻结配置 【步骤6】实例化所有剩余的(非惰性初始化)单例

10.2> 源码解析

我们来看一下负责这部分逻辑的代码:

(五)Spring源码解析:ApplicationContext源码解析

具体的逻辑处理就是在finishBeanFactoryInitialization(beanFactory)的方法中,如下所示:

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
	/** 步骤1:为上下文初始化ConversionService */
	if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && // 是否存在名称为“conversionService”并且类型是ConversionService的Bean
			beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) 
		beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));

	/** 步骤2:如果没有设置EmbeddedValueResolver(嵌入值解析器),则默认添加一个StringValueResolver */
	if (!beanFactory.hasEmbeddedValueResolver()) 
		beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
	
	/** 步骤3:尽早初始化LoadTimeWeaverware类型的Bean,以便尽早注册其转换器 */
	String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
	for (String weaverAwareName : weaverAwareNames) 
		getBean(weaverAwareName);
	
	beanFactory.setTempClassLoader(null); // 停止使用临时ClassLoader进行类型匹配
	beanFactory.freezeConfiguration(); // 冻结配置
	beanFactory.preInstantiateSingletons(); // 实例化所有剩余的(非惰性初始化)单例
}

冻结所有配置

public void freezeConfiguration() {
	this.configurationFrozen = true; // 开启配置冻结开关
	this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
}

初始化非延迟加载单例

public void preInstantiateSingletons() throws BeansException {
	List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
	/** 步骤1:初始化所有非惰性单例bean */
	for (String beanName : beanNames) {
		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
		if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            // 针对FactoryBean创建bean
			if (isFactoryBean(beanName)) {
				Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
				if (bean instanceof FactoryBean) {
					FactoryBean<?> factory = (FactoryBean<?>) bean;
					boolean isEagerInit;
					if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) 
						isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit, getAccessControlContext());
					else 
						isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit());
					if (isEagerInit) // 对于配置了【非惰性加载】的bean执行创建操作
						getBean(beanName);
				}
			} 
            // 针对非FactoryBean创建bean
			else getBean(beanName); 
		}
	}
	/** 步骤2:对于配置了SmartInitializingSingleton的Bean,触发初始化后回调(post-initialization callback)*/
	for (String beanName : beanNames) {
		Object singletonInstance = getSingleton(beanName);
        // 针对SmartInitializingSingleton类型触发初始化后回调,即:afterSingletonsInstantiated
		if (singletonInstance instanceof SmartInitializingSingleton) {
			SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
			if (System.getSecurityManager() != null) 
				AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
					smartSingleton.afterSingletonsInstantiated(); // 触发初始化后回调
					return null;
				}, getAccessControlContext());
			else smartSingleton.afterSingletonsInstantiated(); // 触发初始化后回调
		}
	}
}

在上面代码中,总共执行了如下两个步骤: 【步骤1】步骤1:初始化所有非惰性(isEagerInit)单例bean。即:针对FactoryBean类型创建bean 和 针对其他类型创建bean; 【步骤2】对于配置了SmartInitializingSingleton的Bean,触发初始化后回调,即:调用afterSingletonsInstantiated()方法;

十一、finishRefresh()完成refresh操作

最后这部分,我们来看一下finishRefresh()方法的逻辑代码:

(五)Spring源码解析:ApplicationContext源码解析

finishRefresh()方法中,主要就是针对Lifecycle接口进行处理,该接口主要包含如下两个重要方法:

start() :Spring启动的时候,调用该方法开始生命周期; stop() :Spring关闭的时候,调用该方法结束生命周期;

那么下面我们来看一下在finishRefresh()方法中,它是如何实现这个功能的:

protected void finishRefresh() {
	clearResourceCaches(); // 仅执行清除缓存操作:resourceCaches.clear()
	initLifecycleProcessor(); // 初始化生命周期处理器
	getLifecycleProcessor().onRefresh(); // 启动所有实现了Lifecycle接口的bean
	publishEvent(new ContextRefreshedEvent(this)); // 发布上下文已刷新的事件
	if (!NativeDetector.inNativeImage()) // 判断是不是在GraalVM虚拟机上运行
		LiveBeansView.registerApplicationContext(this);
}

初始化生命周期处理器——LifecycleProcessor

protected void initLifecycleProcessor() {
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    /** 步骤1:如果存在名字是“lifecycleProcessor”的生命周期处理器,则将其赋值给全局变量lifecycleProcessor */
	if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
		this.lifecycleProcessor = beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
        
    /** 步骤2:如果不存在,则创建默认的生命周期处理器——DefaultLifecycleProcessor,并赋值给全局变量lifecycleProcessor */
	else {
		DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
		defaultProcessor.setBeanFactory(beanFactory);
		this.lifecycleProcessor = defaultProcessor;
		beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
	}
}

通过调用onRefresh()方法来启动所有实现了Lifecycle接口的bean

public void onRefresh() {
	startBeans(true); // 启动所有实现了Lifecycle接口的bean
	this.running = true;
}

private void startBeans(boolean autoStartupOnly) {
	Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans(); // 获得所有Lifecycle集合
	Map<Integer, LifecycleGroup> phases = new TreeMap<>();

	/** 步骤1:如果autoStartupOnly是false,或者是SmartLifecycle类型的bean,并且其内部方法isAutoStartup()返回了true,则会保存到phase中 */
	lifecycleBeans.forEach((beanName, bean) -> {
		if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
			int phase = getPhase(bean);
			phases.computeIfAbsent(
					phase,
					p -> new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly)
			).add(beanName, bean);
		}
	});

	/** 步骤2:如果phase中存在待启动的LifecycleGroup,则调用每一个start()方法 */
	if (!phases.isEmpty()) 
		phases.values().forEach(LifecycleGroup::start); // 调用LifecycleGroup的start()方法
}

最后我们发现,会调用到DefaultLifecycleProcessor的内部类LifecycleGroupstart()方法;然后在doStart()方法中最终调用了每一个实现了Lifecycle接口的子类的start()方法。

public void start() {
	if (this.members.isEmpty()) return;
	Collections.sort(this.members);
	for (LifecycleGroupMember member : this.members) 
		doStart(this.lifecycleBeans, member.name, this.autoStartupOnly); // 在Spring中,真正执行某个逻辑都是以do开头的
}

private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName, boolean autoStartupOnly) {
	Lifecycle bean = lifecycleBeans.remove(beanName);
	if (bean != null && bean != this) {
		String[] dependenciesForBean = getBeanFactory().getDependenciesForBean(beanName);
		for (String dependency : dependenciesForBean) 
			doStart(lifecycleBeans, dependency, autoStartupOnly); // 如果有嵌套,则通过递归处理
		
		if (!bean.isRunning() && (!autoStartupOnly || !(bean instanceof SmartLifecycle) || ((SmartLifecycle) bean).isAutoStartup())) {
			try {
				bean.start(); // 调用Lifecycle实现类的start()方法触发生命周期开始操作
			} catch (Throwable ex) {...}
		}
	}
}

今天的文章内容就这些了:

写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的 点赞 & 分享

更多技术干货,欢迎大家关注公众号“爪哇缪斯” ~ \(^o^)/ ~ 「干货分享,每天更新」

转载自:https://juejin.cn/post/7238917620849360951
评论
请登录