0
点赞
收藏
分享

微信扫一扫

【Spring 源码深度解析】05 容器的扩展

12a597c01003 2022-02-19 阅读 106

文章目录


Spring 中提供了一个接口 ApplicationContext,用于扩展 BeanFactory 中现有的功能。ApplicationContext 和 BeanFctory 一样都是用于加载 bean,但是 ApplicationContext 提供了更多的扩展功能,包含了 BeanFctory 的所有功能。

使用 ApplicationContext 加载 XML。

ClassPathXmlApplicationContext bf = new ClassPathXmlApplicationContext("test/base/beanFactoryTest.xml");

下面以 ClassPathXmlApplicationContext作为切入点对整体功能进行分析。

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

public ClassPathXmlApplicationContext(
		String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
		throws BeansException {

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

ClassPathXmlApplicationContext 中可以将配置文件以数组方式传入。对于解析的实现是在 refresh 方法中。

1 设置配置路径

在 ClassPathXmlApplicationContext 中支持多个配置文件以数组方式传入。

public void setConfigLocations(@Nullable String... locations) {
	if (locations != null) {
		Assert.noNullElements(locations, "Config locations must not be 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) {
	// 调用 StandardEnvironment 解析路径
	return getEnvironment().resolveRequiredPlaceholders(path);
}

2 扩展功能

设置完路径后,就可以根据路径作配置文件的解析以及各个功能的实现。在 refresh 中几乎包含了 ApplicationContext 中提供的全部功能。

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// Prepare this context for refreshing.
		//准备刷新的上下文环境
		prepareRefresh();

		// Tell the subclass to refresh the internal bean factory.
		//初始化 BeanFactory,并进行 XML 文件读取 @see #refreshBeanFactory
		// 已经加载完成 BeanDefinitions
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// Prepare the bean factory for use in this context.
		//对 BeanFactory 进行各种功能的填充
		prepareBeanFactory(beanFactory);

		try {
			// Allows post-processing of the bean factory in context subclasses.
			//子类覆盖方法作额外的处理
			postProcessBeanFactory(beanFactory);

			// Invoke factory processors registered as beans in the context.
			//激活各种 BeanFactory 处理器 例如 CustomEditorConfigurer
			invokeBeanFactoryPostProcessors(beanFactory);

			// Register bean processors that intercept bean creation.
			//注册拦截  Bean 创建的 Bea处理器,这里只是注册,真正的调用在 getBean 时候
			registerBeanPostProcessors(beanFactory);

			// Initialize message source for this context.
			//为上下文初始化 Message 源,即不同语言的消息体,国际化处理
			initMessageSource();

			// Initialize event multicaster for this context.
			//初始化应用消息广播器,并放入 "applicationEventMulticaster" bean 中
			initApplicationEventMulticaster();

			// Initialize other special beans in specific context subclasses
			// 留给子类来初始化其它的 bean.
			onRefresh();

			// Check for listener beans and register them.
			//在所有注册的 bean 中查找 Listener bean,注册到消息广播器中
			//注册监听器
			registerListeners();

			// Instantiate all remaining (non-lazy-init) singletons.
			// 初始化剩下的单实例(非惰性的) 非延迟加载单例
			finishBeanFactoryInitialization(beanFactory);

			// Last step: publish corresponding event.
			// 完成刷线过程,通知生命周期处理器 lifecycleProcessor 刷新过程,同时发出 ContextRefreshEvent 通知别人
			finishRefresh();
		}

		catch (BeansException ex) {
			if (logger.isWarnEnabled()) {
				logger.warn("Exception encountered during context initialization - " +
						"cancelling refresh attempt: " + ex);
			}

			// Destroy already created singletons to avoid dangling resources.
			destroyBeans();

			// Reset 'active' flag.
			cancelRefresh(ex);

			// Propagate exception to caller.
			throw ex;
		}

		finally {
			// Reset common introspection caches in Spring's core, since we
			// might not ever need metadata for singleton beans anymore...
			resetCommonCaches();
		}
	}
}

主要逻辑:
1)初始化前的准备工作,例如对系统属性或环境变量进行准备及验证。
在某些情况下项目要读取某些系统变量,而这个变量的设置可能会影响系统的正确性,因此 Spring 提供的 prepareRefresh 方法可以在启动的时候提前对必需的变量进行存在性校验。

2)初始化 BeanFactory,并进行 XML 文件的读取。
ClassPathXmlApplicationContext 包含着 BeanFactory 所提供的一切特征,那么在 obtainFreshBeanFactory 方法中会复用 BeanFactory 中的配置文件读取解析及其它功能,这一步后,ClassPathXmlApplicationContext 实际上就已经包含了 BeanFactory 所提供的功能,也就是可以进行 bean 的提取等基础操作了。

3)对 BeanFactory 进行各种功能的填充。
@Qualifier 和 @Autowired 就是在 prepareBeanFactory(beanFactory) 方法中增加的支持。

4)子类覆盖方法作额外的处理。
提供一个空的函数实现 postProcessBeanFactory 来提供业务扩展的需求。

5)激活各种 BeanFactory 处理器。

6)注册拦截 Bean 创建的 Bean处理器,这里只是注册,真正的调用在 getBean 时候。

7)为上下文初始化 Message 源,即不同语言的消息体,国际化处理。

8)初始化应用消息广播器,并放入 “applicationEventMulticaster” bean 中。

9)留给子类来初始化其它的 bean。

10)在所有注册的 bean 中查找 Listener bean,注册到消息广播器中。

11)初始化剩下的单实例(非惰性的)。

12)完成刷线过程,通知生命周期处理器 lifecycleProcessor 刷新过程,同时发出 ContextRefreshEvent 通知别人。

3 环境准备

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.
	//留给子类覆盖
	//工程在允许时需要用到某个设置(如 VAR)是从系统环境变量中获取的,如果用户没有配置这个参数,工程就不会工作
	//那么就可以扩展 ClassPathXmlApplicationContext 来实现 initPropertySources 方法来实现扩展这个功能
	// @Override
	// protected void initPropertySources() {
	// 		getEnvironment().setRequiredProperties("VAR");
	// }
	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...
	this.earlyApplicationEvents = new LinkedHashSet<>();
}

主要逻辑:
1)initPropertySources:该方法留给子类实现,可以在该方法中进行个性化的属性处理及设置。
2)getEnvironment().validateRequiredProperties():对属性进行验证。

该方法的作用例子:例如,工程在允许时需要用到某个设置(如 VAR)是从系统环境变量中获取的,如果用户没有配置这个参数,工程就不会工作,那么就可以扩展 ClassPathXmlApplicationContext 来实现。

public class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext {

    public MyClassPathXmlApplicationContext(String... configLocations) throws BeansException {
        super(configLocations);
    }

    @Override
    protected void initPropertySources() {
        getEnvironment().setRequiredProperties("VAR");
    }

    public static void main(String[] args) {
        ApplicationContext bf = new MyClassPathXmlApplicationContext("test/customtag/customTag.xml");
        User user = (User) bf.getBean("userBean");
    }
}

上述代码执行中,如果我们没有在环境变量中配置 VAR,那么运行时就会抛异常。

4 加载 BeanFactory

通过 obtainFreshBeanFactory 方法,ApplicationContext 就会包含 BeanFactory 的所有功能。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//初始化 BeanFactory,并进行 XML 读取,并将得到的 BeanFactory 记录在
	//当前实体的属性中
	refreshBeanFactory();
	//返回当前实体的 BeanFactory 属性
	return getBeanFactory();
}

将核心实现委托给了 refreshBeanFactory 方法:

// AbstractRefreshableApplicationContext.java
protected final void refreshBeanFactory() throws BeansException {
	// 清理数据
	if (hasBeanFactory()) {
		destroyBeans();
		closeBeanFactory();
	}
	try {
		// 创建 DefaultListableBeanFactory
		DefaultListableBeanFactory beanFactory = createBeanFactory();
		// 为了序列化指定 id,如果有需要,让这个 BeanFactory 从 id 反序列化到 BeanFactory 对象
		beanFactory.setSerializationId(getId());
		// 定制 BeanFactory,设置相关属性,包括是否允许覆盖同名称的不同定义的对象以及循环依赖
		customizeBeanFactory(beanFactory);
		// 加载 BeanDefinition @see AbstractXmlApplicationContext#loadBeanDefinitions
		loadBeanDefinitions(beanFactory);
		synchronized (this.beanFactoryMonitor) {
			// 使用全局变量记录 BeanFactory 实例
			this.beanFactory = beanFactory;
		}
	}
	catch (IOException ex) {
		throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
	}
}

主要逻辑:
1)创建 DefaultListableBeanFactory。
2)指定序列化指定 id。
3)定制 BeanFactory。
4)加载 BeanDefinition。
5)使用全局变量记录 BeanFactory 实例。

4.1 定制 BeanFactory

这里已经开始对 BeanFactory 的扩展,在基本容器的基础上,增加了是否允许覆盖,是否允许扩展的设置。

protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
// 如果allowBeanDefinitionOverriding 不为空,设置给 beanFactory 相应的属性
	// 此属性的含义:是否允许覆盖同名称的不同定义的对象
	if (this.allowBeanDefinitionOverriding != null) {
		beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
	}
	// 此属性的含义:是否允许 bean 之间存在循环依赖
	if (this.allowCircularReferences != null) {
		beanFactory.setAllowCircularReferences(this.allowCircularReferences);
	}
}

对于 allowBeanDefinitionOverriding 和 setAllowCircularReferences 的自定义配置可以提供子类来重写 customizeBeanFactory 方法实现。

@Override
    protected void customizeBeanFactory(final DefaultListableBeanFactory beanFactory) {
        super.setAllowBeanDefinitionOverriding(false);
        super.setAllowCircularReferences(false);
        super.customizeBeanFactory(beanFactory);
    }

4.2 加载 BeanDefinition

// AbstractXmlApplicationContext.java
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
	// Create a new XmlBeanDefinitionReader for the given BeanFactory.
	//创建 XmlBeanDefinitionReader 来加载解析 XML 文件
	XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

	// Configure the bean definition reader with this context's
	// resource loading environment.
	// 进行环境变量的设置
	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.
	// 对 beanDefinitionReader 进行设置,设置验证模式
	initBeanDefinitionReader(beanDefinitionReader);
	//加载 @see XmlBeanDefinitionReader#loadBeanDefinitions
	loadBeanDefinitions(beanDefinitionReader);
}

在该方法中需要创建 XmlBeanDefinitionReader 来读取解析 XML 文件内容。初始化 XmlBeanDefinitionReader 后就可以进行配置文件的读取了。

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

因为在 XmlBeanDefinitionReader 中已经将之前初始化的 DefaultListableBeanFactory 注册进去了,所以 XmlBeanDefinitionReader 所读取的 BeanDefinitionHolder 都会注册到 DefaultListableBeanFactory 中,即经过此步骤,类型 DefaultListableBeanFactory 的变量 beanFactory 中已经包含了所以解析好的配置。

5 功能扩展

进入 prepareBeanFactory 方法之前,Spring 已经完成了对配置的解析,而 ApplicationContext 在功能上的扩展在此展开。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	// Tell the internal bean factory to use the context's class loader etc.
	//设置 classLoader 为当前 context 的 classLoader
	beanFactory.setBeanClassLoader(getClassLoader());
	//设置 beanFactory 的表达式语言处理器,Spring3 增加了表达式语言的支持,
	//默认可以使用 #{bean.xxx} 的形式来调用相关属性
	//在 AbstractAutowireCapableBeanFactory 的 applyPropertyValues 方法中会使用
	beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
	//为 beanFactory 增加了一个默认的 propertyEditor ,主要是对 bean 的属性等设置管理的一个工具
	beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

	// Configure the bean factory with context callbacks.
	// 添加后置处理器 BeanPostProcessor,在 postProcessBeforeInitialization 方法中
	//会判断 bean 实例时候实现了 Aware 类型的接口,如果是,会注入相应的资源
	//和下面两个设置配合使用。
	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.
	//设置了几个自动装配的特殊规则,例如,如果 一个类中有 ApplicationContext 属性,会将当前的 context 进行自动 setter 注入。
	//和 ApplicationContextAware 结合使用
	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.
	// 在 postProcessAfterInitialization 方法中判断实例化的 bean 是否实现了 ApplicationListener,如果是会将
	// 其会调用 #addApplicationListener 添加
	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

	// Detect a LoadTimeWeaver and prepare for weaving, if found.
	// 增加对 AspectJ 的支持
	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());
	}
}

主要进行以下几个扩展:

  • 增加对 SpEL 语言的支持
  • 增加对属性编辑器的支持
  • 增加对一些内置类,如 EnvironmentAware,MessageSourceAware 的信息注入
  • 增加了依赖功能可忽略的接口
  • 注册一些固定依赖的属性
  • 增加对 AspectJ 的支持
  • 将相关环境变量及属性注册已单例方式注册

5.1 增加对 SpEL 语言的支持

SpEL 全称 Spring 表达式语言(Spring Expression Lanuage),能在运行时构建复杂表达式,存取对象图属性,对象方法调用等。可以用来配置 bean 定义。SpEL 是单独模块,只依赖于 core 模块,可以单独使用。

SlEL 使用 #{…} 作为定界符,所有在大括号中的字符都将被认为是 SpEL,使用格式如下

<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xsi:schemaLocation="
	   http://www.springframework.org/schema/beans
	   http://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<!-- SpEL 表达式-->
	<bean id="testA" class="org.springframework.test.autowire.TestA">
		<property name="testB" value="#{testB}" />
	</bean>
	<bean id="testB" class="org.springframework.test.autowire.TestB" />

	<!--相当于-->
	<bean id="testA" class="org.springframework.test.autowire.TestA">
		<property name="testB" ref="testB" />
	</bean>
	<bean id="testB" class="org.springframework.test.autowire.TestB" />
</beans>

在源码中通过beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));来注册解析器,就可以对 SpEL 表达式进行解析了。

Spring 是在什么时候调用这个解析器进行解析的?Spring 在进行初始化 bean 的时候会调用 populateBean 方法填充属性时,会调用 AbstractAutowireCapableBeanFactory 的 applyPropertyValues 方法中会完成解析功能。在这个函数中会通过 BeanDefinitionValueResolver 的实例 valueResolver 来进行属性值的解析。通过 valueResolver 的 resolveValueIfNecessary 方法中调用 evaluate->doEvaluate 方法,最后的功能是由 AbstractBeanFactory#evaluateBeanDefinitionString 方法实现的。

// BeanDefinitionValueResolver
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
	// We must check each value to see whether it requires a runtime reference
	// to another bean to be resolved.
	if (value instanceof RuntimeBeanReference) {
		RuntimeBeanReference ref = (RuntimeBeanReference) value;
		return resolveReference(argName, ref);
	}
	else if (value instanceof RuntimeBeanNameReference) {
		String refName = ((RuntimeBeanNameReference) value).getBeanName();
		refName = String.valueOf(doEvaluate(refName));
		if (!this.beanFactory.containsBean(refName)) {
			throw new BeanDefinitionStoreException(
					"Invalid bean name '" + refName + "' in bean reference for " + argName);
		}
		return refName;
	}
	else if (value instanceof BeanDefinitionHolder) {
		// Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.
		BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
		return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
	}
	else if (value instanceof BeanDefinition) {
		// Resolve plain BeanDefinition, without contained name: use dummy name.
		BeanDefinition bd = (BeanDefinition) value;
		String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR +
				ObjectUtils.getIdentityHexString(bd);
		return resolveInnerBean(argName, innerBeanName, bd);
	}
	else if (value instanceof ManagedArray) {
		// May need to resolve contained runtime references.
		ManagedArray array = (ManagedArray) value;
		Class<?> elementType = array.resolvedElementType;
		if (elementType == null) {
			String elementTypeName = array.getElementTypeName();
			if (StringUtils.hasText(elementTypeName)) {
				try {
					elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
					array.resolvedElementType = elementType;
				}
				catch (Throwable ex) {
					// Improve the message by showing the context.
					throw new BeanCreationException(
							this.beanDefinition.getResourceDescription(), this.beanName,
							"Error resolving array type for " + argName, ex);
				}
			}
			else {
				elementType = Object.class;
			}
		}
		return resolveManagedArray(argName, (List<?>) value, elementType);
	}
	else if (value instanceof ManagedList) {
		// May need to resolve contained runtime references.
		return resolveManagedList(argName, (List<?>) value);
	}
	else if (value instanceof ManagedSet) {
		// May need to resolve contained runtime references.
		return resolveManagedSet(argName, (Set<?>) value);
	}
	else if (value instanceof ManagedMap) {
		// May need to resolve contained runtime references.
		return resolveManagedMap(argName, (Map<?, ?>) value);
	}
	else if (value instanceof ManagedProperties) {
		Properties original = (Properties) value;
		Properties copy = new Properties();
		original.forEach((propKey, propValue) -> {
			if (propKey instanceof TypedStringValue) {
				propKey = evaluate((TypedStringValue) propKey);
			}
			if (propValue instanceof TypedStringValue) {
				propValue = evaluate((TypedStringValue) propValue);
			}
			if (propKey == null || propValue == null) {
				throw new BeanCreationException(
						this.beanDefinition.getResourceDescription(), this.beanName,
						"Error converting Properties key/value pair for " + argName + ": resolved to null");
			}
			copy.put(propKey, propValue);
		});
		return copy;
	}
	else if (value instanceof TypedStringValue) {
		// Convert value to target type here.
		TypedStringValue typedStringValue = (TypedStringValue) value;
		Object valueObject = evaluate(typedStringValue);
		try {
			Class<?> resolvedTargetType = resolveTargetType(typedStringValue);
			if (resolvedTargetType != null) {
				return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
			}
			else {
				return valueObject;
			}
		}
		catch (Throwable ex) {
			// Improve the message by showing the context.
			throw new BeanCreationException(
					this.beanDefinition.getResourceDescription(), this.beanName,
					"Error converting typed String value for " + argName, ex);
		}
	}
	else if (value instanceof NullBean) {
		return null;
	}
	else {
		// 其它值如 #{xxx}
		return evaluate(value);
	}
}

// 其它值如 #{xxx}
protected Object evaluate(@Nullable Object value) {
	if (value instanceof String) {
		return doEvaluate((String) value);
	}
	else if (value instanceof String[]) {
		String[] values = (String[]) value;
		boolean actuallyResolved = false;
		Object[] resolvedValues = new Object[values.length];
		for (int i = 0; i < values.length; i++) {
			String originalValue = values[i];
			Object resolvedValue = doEvaluate(originalValue);
			if (resolvedValue != originalValue) {
				actuallyResolved = true;
			}
			resolvedValues[i] = resolvedValue;
		}
		return (actuallyResolved ? resolvedValues : values);
	}
	else {
		return value;
	}
}

private Object doEvaluate(@Nullable String value) {
	return this.beanFactory.evaluateBeanDefinitionString(value, this.beanDefinition);
}

// AbstractBeanFactory.java
protected Object evaluateBeanDefinitionString(@Nullable String value, @Nullable BeanDefinition beanDefinition) {
	// 判断是否存在 SpEL 解析的存在 通过 AbstractApplicationContext#prepareBeanFactory 方法
	// 注入 StandardBeanExpressionResolver 解析器
	if (this.beanExpressionResolver == null) {
		return value;
	}

	Scope scope = null;
	if (beanDefinition != null) {
		String scopeName = beanDefinition.getScope();
		if (scopeName != null) {
			scope = getRegisteredScope(scopeName);
		}
	}
	//解析功能由 StandardBeanExpressionResolver 内部实现,由 SpelExpressionParser 解析
	return this.beanExpressionResolver.evaluate(value, new BeanExpressionContext(this, scope));
}

调用 evaluateBeanDefinitionString 方法时会判断是否存在语言解析器,解析的过程是在 Spring 的 expression 包内。应用解析器的调用主要在解析依赖注入 bean 的时候,以及在完成 bean 的初始化和属性获取后进行属性填充的时候

5.2 增加属性注册编辑器

在 Spring DI 注入的时候,可以把普通属性注册进来,但是像 Date 类型就无法被识别。例如

public class UserManager {

	private Date dateValue;

	public Date getDateValue() {
		return dateValue;
	}

	public void setDateValue(Date dateValue) {
		this.dateValue = dateValue;
	}

	@Override
	public String toString() {
		return "UserManager{" +
				"dateValue=" + dateValue +
				'}';
	}
}

对日期进行注入

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xsi:schemaLocation="
	   http://www.springframework.org/schema/beans
	   http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="userManager" class="org.springframework.test.propertyeditor.UserManager">
		<property name="dateValue" value="2020-08-06"/>
	</bean>
</beans>

测试代码

public class Main {

	public static void main(String[] args) {
		ClassPathXmlApplicationContext factory = new ClassPathXmlApplicationContext("test/propertyeditor/bean.xml");
		UserManager userManager = (UserManager) factory.getBean("userManager");

		System.out.println(userManager);
	}
}

如果直接这样使用,程序会抛出类型转换异常。因为在 UserManager 中的 dateValue 是 Date 类型,而 XML 中的是 String 类型。对于该情况,Spring 有两种解决方式。

5.2.1 使用自定义属性编辑器

通过继承 PropertyEditorSupport,重写 setAsText 方法。具体步骤如下:
1)编写自定义属性编辑器

public class DatePropertyEditor extends PropertyEditorSupport {

	private String format = "yyyy-MM-dd";

	public void setFormat(String format) {
		this.format = format;
	}

	@Override
	public void setAsText(String text) throws IllegalArgumentException {
		SimpleDateFormat dateFormat = new SimpleDateFormat(format);
		try {
			Date date = dateFormat.parse(text);
			this.setValue(date);
		} catch (ParseException e) {
			e.printStackTrace();
		}
	}
}

2)将自定义属性编辑器注册到 Spring 中

<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
	<property name="customEditors">
		<map>
			<!-- spring 4.0 的写法-->
			<entry key="java.util.Date" value="org.springframework.test.propertyeditor.DatePropertyEditor"/>
		</map>
	</property>
</bean>

在配置文件中引入类型为 org.springframework.beans.factory.config.CustomEditorConfigurer 的 bean,并在 customEditors 中加入自定义的属性编辑器,其中 key 为属性编辑器所对应的类型。这样在 Spring 注入 bean 的属性时遇到 java.util.Date 类型的属性会自动调用自定义的 DatePropertyEditor 解析器进行解析,并用解析结果进行注入。

5.2.2 注册 Spring 自带的属性编辑器 CustomDateEditor

主要步骤如下
1)自定义属性编辑器

public class DatePropertyEditorRegistrar implements PropertyEditorRegistrar {

	/**
	 * 进行自定义属性注册器注册
	 * @param registry the {@code PropertyEditorRegistry} to register the
	 */
	@Override
	public void registerCustomEditors(PropertyEditorRegistry registry) {
		registry.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
	}
}

注册到 Spring 中

<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
	<property name="propertyEditorRegistrars">
		<array>
			<bean class="org.springframework.test.propertyeditor.custom.DatePropertyEditorRegistrar" />
		</array>
	</property>
</bean>

通过在配置文件中将自定义的 DatePropertyEditorRegistrar 注册进入 CustomEditorConfigurer 的 propertyEditorRegistrars 属性中与方法1有相同的效果。

5.2.3 注册源码

注册自定义属性编辑的时候使用的是PropertyEditorRegistrar#registerCustomEditors方法,而这里使用的是 ConfigurableListableBeanFactory#addPropertyEditorRegistrar(resourceEditorRegistrar)方法。在 ResourceEditorRegistrar 源码中进行分析。查看 registerCustomEditors 的源码。

public void registerCustomEditors(PropertyEditorRegistry registry) {
	ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.propertyResolver);
	doRegisterEditor(registry, Resource.class, baseEditor);
	doRegisterEditor(registry, ContextResource.class, baseEditor);
	doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
	doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
	doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
	doRegisterEditor(registry, Path.class, new PathEditor(baseEditor));
	doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor));
	doRegisterEditor(registry, URL.class, new URLEditor(baseEditor));

	ClassLoader classLoader = this.resourceLoader.getClassLoader();
	doRegisterEditor(registry, URI.class, new URIEditor(classLoader));
	doRegisterEditor(registry, Class.class, new ClassEditor(classLoader));
	doRegisterEditor(registry, Class[].class, new ClassArrayEditor(classLoader));

	//自定义属性属性编辑器的注册
	if (this.resourceLoader instanceof ResourcePatternResolver) {
		doRegisterEditor(registry, Resource[].class,
				new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader, this.propertyResolver));
	}
}

上述代码完成内置的属性编辑器的注册后,调用 doRegisterEditor 方法进行自定义属性编辑器的注册。

private void doRegisterEditor(PropertyEditorRegistry registry, Class<?> requiredType, PropertyEditor editor) {
	// 如果
	if (registry instanceof PropertyEditorRegistrySupport) {
		((PropertyEditorRegistrySupport) registry).overrideDefaultEditor(requiredType, editor);
	}
	else {
		registry.registerCustomEditor(requiredType, editor);
	}
}

在 doRegisterEditor 方法中可以看到之前自定义属性中使用的关键代码registry.registerCustomEditor(requiredType, editor);,所以ResourceEditorRegistrar#registerCustomEditors的核心功能就是注册了一系列的常用类型的属性编辑器,在注册后,一旦某个实体 bean 中存在对应类型的属性,Spring 就会调用注册属性编辑器将配置中定义 String 类型转换为对应的类型并进行赋值。

可是beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));方法仅仅是注ResourceEditorRegistrar 实例,却并没有调用 registerCustomEditors 方法进行注册,那到底是在什么时候进行注册的呢?

具体的调用时机如下。

AbstractBeanFactort#initBeanWrapper(BeanWrapper bw) ->
AbstractBeanFactort#registerCustomEditors(PropertyEditorRegistry registry) ->
ResourceEditorRegistrar#registerCustomEditors(PropertyEditorRegistry registry) ->
ResourceEditorRegistrar#doRegisterEditor

// AbstractBeanFactory.java
protected void initBeanWrapper(BeanWrapper bw) {
	bw.setConversionService(getConversionService());
	// 进行属性编辑器的注册
	registerCustomEditors(bw);
}

protected void registerCustomEditors(PropertyEditorRegistry registry) {
	PropertyEditorRegistrySupport registrySupport =
			(registry instanceof PropertyEditorRegistrySupport ? (PropertyEditorRegistrySupport) registry : null);
	if (registrySupport != null) {
		registrySupport.useConfigValueEditors();
	}
	// 如果自定义属性注册器不为空,在 AbstractApplicationContext#prepareBeanFactory 设置了 ResourceEditorRegistrar
	// 可以注入自定义的注册器
	if (!this.propertyEditorRegistrars.isEmpty()) {
		for (PropertyEditorRegistrar registrar : this.propertyEditorRegistrars) {
			try {
				registrar.registerCustomEditors(registry);
			}
			catch (BeanCreationException ex) {
				Throwable rootCause = ex.getMostSpecificCause();
				if (rootCause instanceof BeanCurrentlyInCreationException) {
					BeanCreationException bce = (BeanCreationException) rootCause;
					String bceBeanName = bce.getBeanName();
					if (bceBeanName != null && isCurrentlyInCreation(bceBeanName)) {
						if (logger.isDebugEnabled()) {
							logger.debug("PropertyEditorRegistrar [" + registrar.getClass().getName() +
									"] failed because it tried to obtain currently created bean '" +
									ex.getBeanName() + "': " + ex.getMessage());
						}
						onSuppressedException(ex);
						continue;
					}
				}
				throw ex;
			}
		}
	}
	if (!this.customEditors.isEmpty()) {
		this.customEditors.forEach((requiredType, editorClass) ->
				registry.registerCustomEditor(requiredType, BeanUtils.instantiateClass(editorClass)));
	}
}

可以看到最初调用是在 initBeanWrapper 方法中,该方法是 bean 在实例化 instantiateBean 方法的时候使用的。因此在 bean 的初始化后会调用 ResourceEditorRegistrar 的 registerCustomEditors 方法进行批量通用属性编辑器注册。

BeanWrapper 是用于封装 bean 实例的。其间接继承了 PropertyEditorRegistry 类型,也就是出现的 registry。BeanWrapper 的默认实现是 BeanWrapperImpl,其还间接继承了 ResourceEditorRegistrarSupport 类。在 ResourceEditorRegistrarSupport 中有这样一个方法。

private void createDefaultEditors() {
	this.defaultEditors = new HashMap<>(64);

	// Simple editors, without parameterization capabilities.
	// The JDK does not contain a default editor for any of these target types.
	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());
	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.
	// Can be overridden by registering custom instances of those as custom 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);
	}
}

上面定义了一系列常用的个性化属性编辑器。如果我们定义的 bean 中的某个属性的类型不在上面的常用配置中的话,才需要我们进行个性化属性编辑器的注册。

5.3 添加 ApplicationContextAwareProcessor 处理器

完成属性编辑器的注册后,就是beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));方法了,该方法就要就是注册一个 BeanDefinifionProcessor。真正的逻辑是在 ApplicationContextAwareProcessor 中。

ApplicationContextAwareProcessor 实现了 BeanPostProcessor 接口,在 bean 实例化的时候,就是在激活 init-method 的前后会调用 BeanPostPocessor 的 postProcessorBeforeInitialization 和 postProcessorAfterInitialization 方法。

public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
	AccessControlContext acc = null;

	if (System.getSecurityManager() != null &&
			(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
					bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
					bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
		acc = this.applicationContext.getBeanFactory().getAccessControlContext();
	}

	if (acc != null) {
		AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
			//设置 Aware 接口,实现 Aware 接口的 bean 实例化后会获取对应的一些资源
			invokeAwareInterfaces(bean);
			return null;
		}, acc);
	}
	else {
		//设置 Aware 接口,实现 Aware 接口的 bean 实例化后会获取对应的一些资源
		invokeAwareInterfaces(bean);
	}

	return bean;
}

private void invokeAwareInterfaces(Object bean) {
	if (bean instanceof Aware) {
		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 ApplicationContextAware) {
			((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
		}
	}
}

public Object postProcessAfterInitialization(Object bean, String beanName) {
	return bean;
}

postProcessBeforelniti lization 方法中调用了 invokeAwareInterfaces 方法主要进行注入相关的 Aware 接口。

5.4 注册依赖忽略

经过 ApplicationContextAwareProcessor 的 postProcessBeforeInitialization 方法后,一些 bean 已经不是普通的 bean 的,所有需要在 Spring 做 bean 的依赖注入时忽略这些类。

//设置了几个忽略自动装配的接口
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

5.5 注册依赖

//设置了几个自动装配的特殊规则,例如,如果 一个类中有 ApplicationContext 属性,会将当前的 context 进行自动 setter 注入。
//和 ApplicationContextAware 结合使用
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);

当注册了依赖解析后,例如注册了对 BeanFactory.class 的解析依赖后,当 bean 的属性注入的时候,一旦检测到 BeanFactory 类型,便会将 beanFactory 的实例注入。

6 BeanFactory 的后处理

BeanFacotry 作为 Spring 容器功能的基础,用于存放所有已经加载的 bean ,为了保证程序上的高可扩展性,Spring 针对 BeanFactory 了大量的扩展,比如 PostProcessor 等都是在这里实现的。

6.1 激活注册的 BeanFactoryPostProcessor

BeanFactoryPostProcessor 说明:

  • BeanFactoryPostProcessor 和 BeanPostProcessor 类似,可以对 bean 的定义(配置元数据)进行处理。
  • Spring IoC 容器允许 BeanFactoryPostProcessor 在容器实例实例化任何其它 bean 之前读取配置元数据,并修改它。
  • 可以通过实现 Ordered 接口在设置其执行顺序。在实现 BeanFactoryPostProcessor 的同时也可考虑实现 Ordered 接口。
  • 其作用域是容器级别的,只能对本容器的 bean 进行后置处理。
  • 如果像改变实际的 bean 实例(例如从配置元数据创建的对象),最好使用 BeanPostProcessor。

6.1.1 PropertyPlaceholdConfiguer

PropertyPlaceholdConfiguer 是 BeanFactoryPostProcessor 的典型应用。

public class HelloMessage {

	private String message;

	public void setMessage(String message) {
		this.message = message;
	}

	public String getMessage() {
		return message;
	}
}

public class Main {

	public static void main(String[] args) {
		ClassPathXmlApplicationContext factory = new ClassPathXmlApplicationContext("test/bfpostprocessor/bean.xml");
		HelloMessage helloMessage = (HelloMessage) factory.getBean("helloMessage");

		System.out.println(helloMessage.getMessage());
	}
}

配置文件

<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xsi:schemaLocation="
	   http://www.springframework.org/schema/beans
	   http://www.springframework.org/schema/beans/spring-beans.xsd">

	<!-- PropertyPlaceholderConfigurer 在 5.2 被弃用 而使用 PropertySourcesPlaceholderConfigurer-->
	<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>config/bean.properties</value>
			</list>
		</property>
	</bean>

	<bean id="helloMessage" class="org.springframework.test.bfpostprocessor.HelloMessage">
		<property name="message" value="${bean.mes}"/>
	</bean>
</beans>

上述的 ${bean.mes} 可以在 bean.properties 中进行配置。PropertyPlaceholderConfigurer 间接继承了 BeanFactoryPostProcessor 接口。实现该接口的类,在 Spring 加载过程中,会在 bean 工厂载入所有 bean 配置后执行 postProcessBeanFactory 方法。

// PropertyResourceConfigurer.java
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
	try {
		Properties mergedProps = mergeProperties();

		// Convert the merged properties, if necessary.
		convertProperties(mergedProps);

		// Let the subclass process the properties.
		processProperties(beanFactory, mergedProps);
	}
	catch (IOException ex) {
		throw new BeanInitializationException("Could not load properties", ex);
	}
}

// PropertyPlaceholderConfigurer.java
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props)
	throws BeansException {

	StringValueResolver valueResolver = new PlaceholderResolvingStringValueResolver(props);
	doProcessProperties(beanFactoryToProcess, valueResolver);
}

// PlaceholderConfigurerSupport.java
protected void doProcessProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
	StringValueResolver valueResolver) {

	BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver);

	String[] beanNames = beanFactoryToProcess.getBeanDefinitionNames();
	//对每个 bean 进行解析
	for (String curName : beanNames) {
		// Check that we're not parsing our own bean definition,
		// to avoid failing on unresolvable placeholders in properties file locations.
		if (!(curName.equals(this.beanName) && beanFactoryToProcess.equals(this.beanFactory))) {
			BeanDefinition bd = beanFactoryToProcess.getBeanDefinition(curName);
			try {
				//访问者模式
				visitor.visitBeanDefinition(bd);
			}
			catch (Exception ex) {
				throw new BeanDefinitionStoreException(bd.getResourceDescription(), curName, ex.getMessage(), ex);
			}
		}
	}

	// New in Spring 2.5: resolve placeholders in alias target names and aliases as well.
	beanFactoryToProcess.resolveAliases(valueResolver);

	// New in Spring 3.0: resolve placeholders in embedded values such as annotation attributes.
	beanFactoryToProcess.addEmbeddedValueResolver(valueResolver);
}

在 PropertyResourceConfigurer 类中实现了postProcessBeanFactory 方法,在方法中先后调用 mergeProperties,convertProperties,processProperties 这3个方法 分别得到配置,将得到配置转换为合适的类型,最后将配置内容容告知 BeanFactory。

正是通过实现 BeanFactoryPostProcessor 接口,BeanFactory 在实例化任何 bean 之前获得配置信息,从而能够正确解析 bean 描述文件中的变量引用。

6.1.2 使用自定义的 BeanFactoryPostProcessor

举一个可以屏蔽关键字的例子。

/**
 * 自定义 BeanFactoryPostProcessor
 * 屏蔽关键词
 */
public class ObscenityRemovingBeanFactoryProcessor implements BeanFactoryPostProcessor {

	private Set<String> obscenities = new HashSet<>();

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		String[] names = beanFactory.getBeanDefinitionNames();

		for (String name : names) {
			//获取配置对应的 BeanDefinition
			BeanDefinition bd = beanFactory.getBeanDefinition(name);
			//值解析
			StringValueResolver valueResolver = (strVal) -> isObscene(strVal) ? "*****" : strVal;

			BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver);
			visitor.visitBeanDefinition(bd);
		}
	}

	public boolean isObscene(Object obj) {
		return this.obscenities.contains(obj.toString().toUpperCase());
	}

	public void setObscenities(Set<String> obscenities) {
		obscenities.forEach(str -> this.obscenities.add(str.toUpperCase()));
	}
}

// bean 对象
public class SimPostProcessor {

	private String username;

	private String password;

	private String connectionString;

	public void setUsername(String username) {
		this.username = username;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public void setConnectionString(String connectionString) {
		this.connectionString = connectionString;
	}

	@Override
	public String toString() {
		return "SimPostProcessor{" +
				"username='" + username + '\'' +
				", password='" + password + '\'' +
				", connectionString='" + connectionString + '\'' +
				'}';
	}
}

public class Main {

	public static void main(String[] args) {
		ClassPathXmlApplicationContext factory = new ClassPathXmlApplicationContext("test/bfpostprocessor/self/bean.xml");
		SimPostProcessor simPostProcessor = (SimPostProcessor) factory.getBean("simpleBean");

		System.out.println(simPostProcessor);
	}
}

配置文件

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:tx="http://www.springframework.org/schema/tx"
	   xsi:schemaLocation="
	   http://www.springframework.org/schema/beans
	   http://www.springframework.org/schema/beans/spring-beans.xsd
	   http://www.springframework.org/schema/tx
	   http://www.springframework.org/schema/tool/spring-tx.xsd">

	<bean class="org.springframework.test.bfpostprocessor.self.ObscenityRemovingBeanFactoryProcessor">
		<property name="obscenities">
			<set>
				<value>傻子</value>
				<value>二货</value>
				<value>傻叉</value>
			</set>
		</property>
	</bean>

	<bean id="simpleBean" class="org.springframework.test.bfpostprocessor.self.SimPostProcessor">
		<property name="username" value="傻子" />
		<property name="password" value="123456" />
		<property name="connectionString" value="二货" />
	</bean>
</beans>

输出结果,看到关键字已被屏蔽

SimPostProcessor{username='*****', password='123456', connectionString='*****'}

6.1.3 激活 BeanFactoryPostProcessor

BeanFactoryPostProcessor 的调用过程。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
	// 委托 PostProcessorRegistrationDelegate 进行处理,
	// 传入Bean工厂并获取容器中的Bean工厂后置处理器(注意这里Bean工厂后置处理器还没有初始化)
	PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

	// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
	// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
	if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
		beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
		beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
	}
}

具体实现过程由 PostProcessorRegistrationDelegate 的 invokeBeanFactoryPostProcessors 方法实现。

public static void invokeBeanFactoryPostProcessors(
	ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

	// Invoke BeanDefinitionRegistryPostProcessors first, if any.
	// 1. 先对 BeanDefinitionRegistryPostProcessor 进行处理
	Set<String> processedBeans = new HashSet<>();

	//对 BeanDefinitionRegistry 类型的处理
	if (beanFactory instanceof BeanDefinitionRegistry) {
		BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
		//保存硬编码添加的 BeanFactoryPostProcessor
		List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
		//保存硬编码添加的 BeanDefinitionRegistryPostProcessor
		List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
		// 硬编码注册的后处理器
		for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
			//如果是 BeanDefinitionRegistryPostProcessor 类型
			if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
				BeanDefinitionRegistryPostProcessor registryProcessor =
						(BeanDefinitionRegistryPostProcessor) postProcessor;
				// 对于 BeanDefinitionRegistryPostProcessor 类型,在 BeanFactoryPostProcessor 基础上还有自己
				//定义的方法,需要先调用
				registryProcessor.postProcessBeanDefinitionRegistry(registry);
				registryProcessors.add(registryProcessor);
			}
			else {
				//记录常规 BeanFactoryPostProcessor
				regularPostProcessors.add(postProcessor);
			}
		}

		// Do not initialize FactoryBeans here: We need to leave all regular beans
		// uninitialized to let the bean factory post-processors apply to them!
		// Separate between BeanDefinitionRegistryPostProcessors that implement
		// PriorityOrdered, Ordered, and the rest.
		//定义一个集合用户保存当前准备创建的 BeanDefinitionRegistryPostProcessor
		List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

		// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
		// 对于配置中读取的 BeanFactoryPostProcessor 的处理
		// 实现了 PriorityOrdered 排序接口
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
		for (String ppName : postProcessorNames) {
			//判断是否实现了PriorityOrdered接口的
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				//显示的调用getBean()的方式获取出该对象然后加入到currentRegistryProcessors集合中去
				currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
				//同时也加入到processedBeans集合中去
				processedBeans.add(ppName);
			}
		}
		//对 currentRegistryProcessors 集合中 BeanDefinitionRegistryPostProcessor 进行排序
		sortPostProcessors(currentRegistryProcessors, beanFactory);
		//把他加入到用于保存到 registryProcessors 中
		registryProcessors.addAll(currentRegistryProcessors);
		/*
		 * 在这里典型的 BeanDefinitionRegistryPostProcessor 就是 ConfigurationClassPostProcessor
		 * 用于进行 bean 定义的加载 比如我们的包扫描,@import等
		 */
		invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
		currentRegistryProcessors.clear();

		// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
		//下一步 又去容器中获取 BeanDefinitionRegistryPostProcessor 的 bean 的处理器名称
		// 对实现了 Ordered 排序接口进行处理
		postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
		for (String ppName : postProcessorNames) {
			if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
				currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
				processedBeans.add(ppName);
			}
		}
		sortPostProcessors(currentRegistryProcessors, beanFactory);
		registryProcessors.addAll(currentRegistryProcessors);
		//调用他的后置处理方法
		invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
		currentRegistryProcessors.clear();

		// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
		//调用没有实现任何优先级接口的BeanDefinitionRegistryPostProcessor
		//定义一个重复处理的开关变量 默认值为true
		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);
			currentRegistryProcessors.clear();
		}

		// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
		//调用实现了BeanDefinitionRegistryPostProcessor的接口 他是他也同时实现了BeanFactoryPostProcessor的方法
		invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
		//调用BeanFactoryPostProcessor
		invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
	}

	else {
		// Invoke factory processors registered with the context instance.
		//若当前的beanFactory没有实现了BeanDefinitionRegistry 直接调用beanFactoryPostProcessor接口的方法进行后置处理
		invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
	}

	// Do not initialize FactoryBeans here: We need to leave all regular beans
	// uninitialized to let the bean factory post-processors apply to them!
	//最后一步 获取容器中所有的 BeanFactoryPostProcessor
	String[] postProcessorNames =
			beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

	// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
	// Ordered, and the rest.
	//保存BeanFactoryPostProcessor类型实现了priorityOrdered
	List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
	//保存BeanFactoryPostProcessor类型实现了Ordered接口的
	List<String> orderedPostProcessorNames = new ArrayList<>();
	//保存BeanFactoryPostProcessor没有实现任何优先级接口的
	List<String> nonOrderedPostProcessorNames = new ArrayList<>();
	for (String ppName : postProcessorNames) {
		//processedBeans包含的话,表示在上面处理BeanDefinitionRegistryPostProcessor的时候处理过了
		if (processedBeans.contains(ppName)) {
			// skip - already processed in first phase above
		}
		//判断是否实现了PriorityOrdered
		else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
			priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
		}
		//判断是否实现了Ordered
		else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
			orderedPostProcessorNames.add(ppName);
		}
		else {
			nonOrderedPostProcessorNames.add(ppName);
		}
	}

	// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
	//先调用BeanFactoryPostProcessor实现了PriorityOrdered接口的
	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
	invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

	// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
	//再调用BeanFactoryPostProcessor实现了Ordered.
	List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
	for (String postProcessorName : orderedPostProcessorNames) {
		orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
	}
	sortPostProcessors(orderedPostProcessors, beanFactory);
	invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

	// Finally, invoke all other BeanFactoryPostProcessors.
	//调用没有实现任何方法接口的
	List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
	for (String postProcessorName : nonOrderedPostProcessorNames) {
		nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
	}
	invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

	// Clear cached merged bean definitions since the post-processors might have
	// modified the original metadata, e.g. replacing placeholders in values...
	beanFactory.clearMetadataCache();
}

对于 BeanFactoryPostProcessor 的处理主要分两种情况进行处理。对于 BeanFactoryRegistry 的特殊处理,一是对普通 BeanFactoryPostProcessor 进行处理。但是对于每种情况都需要考虑硬编码注入注册的后处理器以及通过配置注入的后处理器。

1)BeanFactoryRegistry 类型的处理
(1)对于硬编码注册的后处理器的处理,主要是通过 AbstractApplicationContext 中的添加处理器方法 addBeanFactoryPostProcessor进行添加。

public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
Assert.notNull(postProcessor, "BeanFactoryPostProcessor must not be null");
	this.beanFactoryPostProcessors.add(postProcessor);
}

添加的后处理器会存放在 beanFactoryPostProcessors 中,在处理 BeanFactoryPostProcessor 的时候,会首先检测 beanFactoryPostProcessors 中有无数据。BeanFactoryRegistryPostProcessor 继承自 BeanFactoryPostProcessor,会有自定义的方法,需要先进行处理。所以,这里需要从 beanFactoryPostProcessors 中挑出 BeanDefinitionRegistryPostProcessor 后处理器,并进行其 postProcessBeanDefinitionRegistry 方法的激活。

(2)记录后处理器主要使用 3 个 List 实现。

  • registryPostProcessors:记录通过硬编码方式注册的 BeanFactoryRegistryPostProcessor 类型的处理器。
  • ruguarPostProcessors:记录通过硬编码方式注册的 BeanFactoryPostProcessor 类型的处理器。
  • registryPostProcessorBeans:记录通过配置方式注册的 BeanFactoryRegistryPostProcessor 类型的处理器。

(3)对以上所记录的 List 中的后处理进行统一调用 BeanFactoryPostProcessor 的 postProcessBeanFactory 方法。
(4)对 beanFactoryPostProcessors 中非 BeanFactoryRegistryPostProcessor 类型的后处理器进行统一的 postProcessBeanFactory 方法调用。

2)普通 beanFactory 的处理。
对于传入的 ConfigurableListableBeanFactory 不是 BeanFactoryRegistry,那么就直接进行 BeanFactoryPostProcessor 的处理。处理方式和上述差不多。

注意的是硬编码添加的后处理器不需要做排序,而配置方式添加的按照 PriorityOrdered 或 Ordered 的顺序调用。

6.2 注册 BeanPostProcessor

这里只是注册 BeanPostProcessor,而调用是在 bean 实例化的时候进行的。Spring 中的大部分功能是通过后处理器的扩展实现的,是 Spring 框架的一个特性。但是 BeanFactory 中并没有实现后处理器的自动注册,在 ApplicationContext 中添加了自动注册的功能。

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
	PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

可以看到实际的逻辑处理也是委托给 PostProcessorRegistrationDelegate 实现。

public static void registerBeanPostProcessors(
	ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

	String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

	// Register BeanPostProcessorChecker that logs an info message when
	// a bean is created during BeanPostProcessor instantiation, i.e. when
	// a bean is not eligible for getting processed by all BeanPostProcessors.
	// BeanPostProcessorChecker 是一个普通的信息打印,可能会有 Spring 的配置中的后处理器
	// 还没有被注册就已经开始了 bean 的初始化,便会打印出 BeanPostProcessorChecker 中的信息
	int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
	beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

	// Separate between BeanPostProcessors that implement PriorityOrdered,
	// Ordered, and the rest.
	// PriorityOrdered 排序
	List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
	//MergedBeanDefinitionPostProcessor
	List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
	// Ordered 排序
	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);
		}
	}

	// First, register the BeanPostProcessors that implement PriorityOrdered.
	// 第一步,注册所有实现 PriorityOrdered 接口的 BeanPostProcessor
	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
	registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

	// Next, register the BeanPostProcessors that implement Ordered.
	//第二步,注册所有实现 Ordered 接口的 BeanPostProcessor
	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);

	// Now, register all regular BeanPostProcessors.
	// 注册无序的 BeanPostProcessor
	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);

	// Finally, re-register all internal BeanPostProcessors.
	//第四步,注册 MergedBeanDefinitionPostProcessor 类型的 BeanPostProcessor,
	// 在 registerBeanPostProcessors 方法是会先移除已存在的 beanPostProcessor
	sortPostProcessors(internalPostProcessors, beanFactory);
	registerBeanPostProcessors(beanFactory, internalPostProcessors);

	// Re-register post-processor for detecting inner beans as ApplicationListeners,
	// moving it to the end of the processor chain (for picking up proxies etc).
	// 添加 ApplicationListener 探测器
	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

private static void registerBeanPostProcessors(
	ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
	// 将 beanPostProcessor 注册到 beanFactory 中
	for (BeanPostProcessor postProcessor : postProcessors) {
		beanFactory.addBeanPostProcessor(postProcessor);
	}
}

// AbstractBeanFactory.java
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
	Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
	// Remove from old position, if any
	// 首先移除旧的
	this.beanPostProcessors.remove(beanPostProcessor);
	// Track whether it is instantiation/destruction aware
	if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
		this.hasInstantiationAwareBeanPostProcessors = true;
	}
	if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
		this.hasDestructionAwareBeanPostProcessors = true;
	}
	// Add to end of list
	this.beanPostProcessors.add(beanPostProcessor);
}

6.3 初始化消息资源

该方法的作用是配置 MessageSource,用作国际化处理。

protected void initMessageSource() {
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
		// 如果在配置中以及配置了 messageSource,那么将 messageSource 提取并记录在 this.messageSource 中
		this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
		// Make MessageSource aware of parent MessageSource.
		if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
			HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
			if (hms.getParentMessageSource() == null) {
				// Only set parent context as parent MessageSource if no parent MessageSource
				// registered already.
				hms.setParentMessageSource(getInternalParentMessageSource());
			}
		}
		if (logger.isTraceEnabled()) {
			logger.trace("Using MessageSource [" + this.messageSource + "]");
		}
	}
	else {
		// Use empty MessageSource to be able to accept getMessage calls.
		//如果没有配置,则使用临时的 DelegatingMessageSource 以便作为调用 getMessage 方法的方法
		DelegatingMessageSource dms = new DelegatingMessageSource();
		dms.setParentMessageSource(getInternalParentMessageSource());
		this.messageSource = dms;
		beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
		if (logger.isTraceEnabled()) {
			logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
		}
	}
}

MessageSource 主要类图
在这里插入图片描述

  • ResourceBundleMessageSource:基于 java 基类 ResourceBundle 实现,允许仅通过资源名加载国际化资源。
  • ReloadableResourceBundleMessageSource:提供定时刷新,允许在不重启系统的情况下,更新资源。
  • StaticMessageSource:用于程序测试,允许提供变成的方式提供国际化信息。
  • DelegatingMessageSource:为了方便操作父 MessageSource 而提供的代理类。

6.4 初始化 ApplicationEventMulticaster

Spring 事件监听的用法。

1)定义监听事件

public class TestEvent extends ApplicationEvent {

	private String message;
	/**
	 * Create a new ApplicationEvent.
	 *
	 * @param source the object on which the event initially occurred (never {@code null})
	 */
	public TestEvent(Object source) {
		super(source);
	}

	public TestEvent(Object source, String message) {
		super(source);
		this.message = message;
	}

	public void print() {
		System.out.println(this.message);
	}
}

2)定义监听器

public class TestListener implements ApplicationListener {

	//listener
	@Override
	public void onApplicationEvent(ApplicationEvent event) {
		if (event instanceof TestEvent) {
			TestEvent testEvent = (TestEvent) event;
			testEvent.print();
		}
	}
}

3)添加配置文件

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xsi:schemaLocation="
	   http://www.springframework.org/schema/beans
	   http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="testListener" class="org.springframework.test.listener.TestListener" />
</beans>

4)测试

public class Main {

	public static void main(String[] args) {
		ClassPathXmlApplicationContext factory = new ClassPathXmlApplicationContext("test/listener/bean.xml");
		TestEvent testEvent = new TestEvent("hello", "msg");
		//发布事件
		factory.publishEvent(testEvent);
	}
}

当程序运行时,Spring 会将发出的 TestEvent 事件转发给 TestListener 监听器进行处理。这是观察者模式的典型应用。

initApplicationEventMulticaster 方法中的处理。考虑了两种情况。

  1. 如果自定义了事件广播器,那么使用用户自定义的。
  2. 如果没有自定义,使用默认的 ApplicationEventMulticaster。即 SimpleApplicationEventMulticaster。
protected void initApplicationEventMulticaster() {
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	//如果自定义事件广播器 beanName 为 applicationEventMulticaster
	if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
		this.applicationEventMulticaster =
				beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
		if (logger.isTraceEnabled()) {
			logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
		}
	}
	else {
		//使用默认的事件广播器
		this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
		beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
		if (logger.isTraceEnabled()) {
			logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
					"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
		}
	}
}

广播器是用来存放监听器并在合适的时候调用监听器。可以 SimpleApplicationEventMulticaster 的实现。每个监听器都可以监听到发布的事件,但是处理与否由自己决定。

// SimpleApplicationEventMulticaster.java
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) {
		String msg = ex.getMessage();
		if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
			// Possibly a lambda-defined listener which we could not resolve the generic event type for
			// -> let's suppress the exception and just log a debug message.
			Log logger = LogFactory.getLog(getClass());
			if (logger.isTraceEnabled()) {
				logger.trace("Non-matching event type for listener: " + listener, ex);
			}
		}
		else {
			throw ex;
		}
	}
}

如果发布事件,调用 AbstractApplicationContext#publishEvent 方法

public void publishEvent(ApplicationEvent event) {
	publishEvent(event, null);
}

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
	Assert.notNull(event, "Event must not be null");

	// Decorate event as an ApplicationEvent if necessary
	ApplicationEvent applicationEvent;
	if (event instanceof ApplicationEvent) {
		applicationEvent = (ApplicationEvent) event;
	}
	else {
		applicationEvent = new PayloadApplicationEvent<>(this, event);
		if (eventType == null) {
			eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
		}
	}

	// Multicast right now if possible - or lazily once the multicaster is initialized
	if (this.earlyApplicationEvents != null) {
		this.earlyApplicationEvents.add(applicationEvent);
	}
	else {
		//调用事件广播执行
		getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
	}

	// Publish event via parent context as well...
	if (this.parent != null) {
		if (this.parent instanceof AbstractApplicationContext) {
			((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
		}
		else {
			this.parent.publishEvent(event);
		}
	}
}

6.5 onRefresh

该方法主要留给子类来实现自定义处理。

6.6 注册监听器

调用 AbstractApplicationContext#registerListeners 方法。

protected void registerListeners() {
	// Register statically specified listeners first.
	//硬编码注入的
	for (ApplicationListener<?> listener : getApplicationListeners()) {
		getApplicationEventMulticaster().addApplicationListener(listener);
	}

	// Do not initialize FactoryBeans here: We need to leave all regular beans
	// uninitialized to let post-processors apply to them!
	//配置文件中设置的
	String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
	for (String listenerBeanName : listenerBeanNames) {
		getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
	}

	// Publish early application events now that we finally have a multicaster...
	Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
	this.earlyApplicationEvents = null;
	if (earlyEventsToProcess != null) {
		for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
			getApplicationEventMulticaster().multicastEvent(earlyEvent);
		}
	}
}

7 初始化非延迟加载单例

在 finishBeanFactoryInitialization 方法中完成 BeanFactory 的初始化工作,其中包括 ConversionService 的设置,配置冻结以及非延迟加载的 bean 的初始化工作。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
	// Initialize conversion service for this context.
	//实例化 conversionService 及其设置
	if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
			beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
		beanFactory.setConversionService(
				beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
	}

	// Register a default embedded value resolver if no bean post-processor
	// (such as a PropertyPlaceholderConfigurer bean) registered any before:
	// at this point, primarily for resolution in annotation attribute values.
	// 添加嵌入式值解析器
	if (!beanFactory.hasEmbeddedValueResolver()) {
		beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
	}

	// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
	String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
	for (String weaverAwareName : weaverAwareNames) {
		getBean(weaverAwareName);
	}

	// Stop using the temporary ClassLoader for type matching.
	beanFactory.setTempClassLoader(null);

	// Allow for caching all bean definition metadata, not expecting further changes.
	//冻结所有的 bean 定义,说明注册的 bean 定义将不被修改或任何进一步的处理
	beanFactory.freezeConfiguration();

	// Instantiate all remaining (non-lazy-init) singletons.
	//初始化剩下的单实例(非惰性)
	beanFactory.preInstantiateSingletons();
}

7.1 ConversionService 的设置

对于 String 到 Date 的转换,除了使用自定义类型转换器之外,还可以使用 Converter。使用一个简单的示例了解其用法。

1)定义转换器

public class String2DateConvert implements Converter<String, Date> {

	@Override
	public Date convert(String source) {
		try {
			return new SimpleDateFormat("yyyy-MM-dd").parse(source);
		} catch (ParseException e) {
			e.printStackTrace();
			return null;
		}
	}
}

2)注册

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xsi:schemaLocation="
	   http://www.springframework.org/schema/beans
	   http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
		<property name="converters">
			<bean class="org.springframework.test.convertor.String2DateConvert" />
		</property>
	</bean>
</beans>

3)测试

public class Main {

	public static void main(String[] args) {
		ClassPathXmlApplicationContext factory = new ClassPathXmlApplicationContext("test/convert/bean.xml");
		ConversionService conversionService = (ConversionService) factory.getBean("conversionService");
		Date date = conversionService.convert("2020-05-06", Date.class);
		System.out.println(date);
	}
}

7.2 冻结配置

冻结所有的 bean 定义,说明注册的 bean 定义将不被修改或任何进一步的处理。

// DefaultListableBeanFactory.java
public void freezeConfiguration() {
	this.configurationFrozen = true;
	this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
}

7.3 初始化非延迟加载

AplicationContext 实现的默认行为是在启动时加载所有单例 bean 提前实例化。在 beanFactory.preInstantiateSingletons() 中实现。

// DefaultListableBeanFactory.java
public void preInstantiateSingletons() throws BeansException {
	if (logger.isTraceEnabled()) {
		logger.trace("Pre-instantiating singletons in " + this);
	}

	// Iterate over a copy to allow for init methods which in turn register new bean definitions.
	// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
	List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

	// Trigger initialization of all non-lazy singleton beans...
	for (String beanName : beanNames) {
		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
		//不是抽象 && 是单例 && 不是延迟加载
		if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
			//是 FactoryBean
			if (isFactoryBean(beanName)) {
				Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
				if (bean instanceof FactoryBean) {
					final 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) {
						getBean(beanName);
					}
				}
			}
			else {
				getBean(beanName);
			}
		}
	}

	// Trigger post-initialization callback for all applicable beans...
	for (String beanName : beanNames) {
		Object singletonInstance = getSingleton(beanName);
		if (singletonInstance instanceof SmartInitializingSingleton) {
			final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
			if (System.getSecurityManager() != null) {
				AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
					smartSingleton.afterSingletonsInstantiated();
					return null;
				}, getAccessControlContext());
			}
			else {
				smartSingleton.afterSingletonsInstantiated();
			}
		}
	}
}

8 finishRefresh

Spring 中还提供了 Lifecycle 接口,包含 start/stop 方法,实现此接口后 Spring 保证在启动时调用其 start 方法开始生命周期,并在 Spring 关闭时调用 stop 方法结束生命周期。通常用来配置后台程序,在启动时一直允许(如对MQ进行轮询等)。finishRefresh 保证这一功能的实现。

protected void finishRefresh() {
	// Clear context-level resource caches (such as ASM metadata from scanning).
	//清除资源缓存
	clearResourceCaches();

	// Initialize lifecycle processor for this context.
	// 初始化 LifecycleProcessor,如果自定义了就使用(beanName 为 lifecycleProcessor),
	// 否则使用默认的 DefaultLifecycleProcessor
	initLifecycleProcessor();

	// Propagate refresh to lifecycle processor first.
	// 刷新
	getLifecycleProcessor().onRefresh();

	// Publish the final event.
	//通知刷新事件
	publishEvent(new ContextRefreshedEvent(this));

	// Participate in LiveBeansView MBean, if active.
	LiveBeansView.registerApplicationContext(this);
}

8.1 initLifecycleProcessor

ApplicaitonContext 启动或停止时,他会通过 LifecycleProcessor 来与所有声明的 bean 的周期做状态更新,而在 LifecycleProcessor 的使用前需要初始化。

protected void initLifecycleProcessor() {
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	//如果自定义了生命周期处理器 lifecycleProcessor
	if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
		this.lifecycleProcessor =
				beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
		if (logger.isTraceEnabled()) {
			logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
		}
	}
	else {
		//如果没有,使用默认的处理器
		DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
		defaultProcessor.setBeanFactory(beanFactory);
		this.lifecycleProcessor = defaultProcessor;
		beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
		if (logger.isTraceEnabled()) {
			logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +
					"[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
		}
	}
}

// DefaultLifecycleProcessor.java
@Override
public void start() {
	startBeans(false);
	this.running = true;
}

/**
 * Stop all registered beans that implement {@link Lifecycle} and <i>are</i>
 * currently running. Any bean that implements {@link SmartLifecycle} will be
 * stopped within its 'phase', and all phases will be ordered from highest to
 * lowest value. All beans that do not implement {@link SmartLifecycle} will be
 * stopped in the default phase 0. A bean declared as dependent on another bean
 * will be stopped before the dependency bean regardless of the declared phase.
 */
@Override
public void stop() {
	stopBeans();
	this.running = false;
}

@Override
public void onRefresh() {
	startBeans(true);
	this.running = true;
}

@Override
public void onClose() {
	stopBeans();
	this.running = false;
}

@Override
public boolean isRunning() {
	return this.running;
}

private void startBeans(boolean autoStartupOnly) {
	Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
	Map<Integer, LifecycleGroup> phases = new HashMap<>();
	lifecycleBeans.forEach((beanName, bean) -> {
		if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
			int phase = getPhase(bean);
			LifecycleGroup group = phases.get(phase);
			if (group == null) {
				group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
				phases.put(phase, group);
			}
			group.add(beanName, bean);
		}
	});
	if (!phases.isEmpty()) {
		List<Integer> keys = new ArrayList<>(phases.keySet());
		Collections.sort(keys);
		for (Integer key : keys) {
			//调用 start 方法
			phases.get(key).start();
		}
	}
}

private void stopBeans() {
	Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
	Map<Integer, LifecycleGroup> phases = new HashMap<>();
	lifecycleBeans.forEach((beanName, bean) -> {
		int shutdownPhase = getPhase(bean);
		LifecycleGroup group = phases.get(shutdownPhase);
		if (group == null) {
			group = new LifecycleGroup(shutdownPhase, this.timeoutPerShutdownPhase, lifecycleBeans, false);
			phases.put(shutdownPhase, group);
		}
		group.add(beanName, bean);
	});
	if (!phases.isEmpty()) {
		List<Integer> keys = new ArrayList<>(phases.keySet());
		keys.sort(Collections.reverseOrder());
		for (Integer key : keys) {
			phases.get(key).stop();
		}
	}
}

默认的 DefaultLifecycleProcessor 会循环调用 Spring 日期中实现了 Lifecycle 接口的 bean,并调用其生命周期方法。

8.2 onRefresh

启动所有实现了 Lifecycle 接口的 bean,调用 DefaultLifecycleProcessor#onRefresh 方法

public void onRefresh() {
	startBeans(true);
	this.running = true;
}

private void startBeans(boolean autoStartupOnly) {
	Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
	Map<Integer, LifecycleGroup> phases = new HashMap<>();
	lifecycleBeans.forEach((beanName, bean) -> {
		if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
			int phase = getPhase(bean);
			LifecycleGroup group = phases.get(phase);
			if (group == null) {
				group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
				phases.put(phase, group);
			}
			group.add(beanName, bean);
		}
	});
	if (!phases.isEmpty()) {
		List<Integer> keys = new ArrayList<>(phases.keySet());
		Collections.sort(keys);
		for (Integer key : keys) {
			//调用 start 方法
			phases.get(key).start();
		}
	}
}

8.3 publishEvent

当完成 ApplicationContext 初始化的时候。要通过 Spring 中的事件发布机制来发出 ContextRefreshedEvent 事件,以保证对于的监听器可以做进一步的逻辑处理。

// AbstractApplicationContext.java
public void publishEvent(ApplicationEvent event) {
	publishEvent(event, null);
}

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
	Assert.notNull(event, "Event must not be null");

	// Decorate event as an ApplicationEvent if necessary
	ApplicationEvent applicationEvent;
	if (event instanceof ApplicationEvent) {
		applicationEvent = (ApplicationEvent) event;
	}
	else {
		applicationEvent = new PayloadApplicationEvent<>(this, event);
		if (eventType == null) {
			eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
		}
	}

	// Multicast right now if possible - or lazily once the multicaster is initialized
	if (this.earlyApplicationEvents != null) {
		this.earlyApplicationEvents.add(applicationEvent);
	}
	else {
		//调用事件广播执行
		getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
	}

	// Publish event via parent context as well...
	if (this.parent != null) {
		if (this.parent instanceof AbstractApplicationContext) {
			((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
		}
		else {
			this.parent.publishEvent(event);
		}
	}
}
举报

相关推荐

0 条评论