6 容器的功能扩展

felix.shao2025-02-28

6 容器的功能扩展

前述

 Spring 中提供了另一个接口 ApplicationContext,用于扩展 BeanFactory 中现有的功能,前者具有后者的所有功能,但是更吃内存些。
 两个的用法上不同。

  • 使用 BeanFactory 方式加载 XML。
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("test.xml"));
  • 使用 ApplicationContext 方式加载 XML。
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("test.xml");

 我们以 ClassPathXmlApplicationContext 开始对源码进行分析,代码见 com.stu.spring.context.chapter06.ClassPathXmlAppTest

6.1 设置配置路径

 设置配置路径

 支持多个配置文件以数组方式同时传入。

public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
    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();
		}
	}
}

6.2 拓展功能

 refresh()
public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
    public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 1. 初始化前的准备工作,例如对系统属性或者环境变量进行准备及验证。
			// 准备刷新的上下文环境
			prepareRefresh();

			// 2. 初始化 BeanFactory,并进行 XML 文件读取。
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// 3. 对 BeanFactory 进行各种功能填充。
			prepareBeanFactory(beanFactory);

			try {
				// 4. 子类覆盖方法做额外的处理。
				postProcessBeanFactory(beanFactory);

				// 5. 激活各种 BeanFactory 处理器。
				invokeBeanFactoryPostProcessors(beanFactory);

				// 6. 注册拦截 bean 创建的 bean 处理器,这里只是注册,真正的调用是在 getBean 时候。
				registerBeanPostProcessors(beanFactory);

				// 7. 为上下文初始化 Message 源,即对不同语言的消息体进行国际化处理。
				initMessageSource();

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

				// 9. 留给子类来初始化其他的 bean。
				onRefresh();

				// 10. 在所有注册的 bean 中查找 listener bean,注册到消息广播器中。
				registerListeners();

				// 11. 初始化剩下的单实例(非惰性的)。
				finishBeanFactoryInitialization(beanFactory);

				// 12. 完成刷新过程。通知生命周期处理器 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 exc 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();
			}
		}
	}
}

 refresh 函数包含了几乎 ApplicationContext 中提供的全部功能,而且此函数中逻辑非常清晰,以下是主要的步骤。

  1. 初始化前的准备工作,例如对系统属性或者环境变量进行准备及验证。

 它可以在 Spring 启动的时候提前对必须的变量进行存在性验证。
2. 初始化 BeanFactory,并进行 XML 文件读取。

 复用的 BeanFactory 所提供的功能,也就是可以进行 bean 的提取等基础操作了。
3. 对 BeanFactory 进行各种功能填充。

 @Qualifier 与 @Autowired 正是在这一步骤中增加的支持。
4. 子类覆盖方法做额外的处理。

 可以很方便的拓展已经存在的功能,如 postProcessBeanFactory 的拓展。
5. 激活各种 BeanFactory 处理器。
6. 注册拦截 bean 创建的 bean 处理器,这里只是注册,真正的调用是在 getBean 时候。
7. 为上下文初始化 Message 源,即对不同语言的消息体进行国际化处理。
8. 初始化应用消息广播器,并放入 ApplicationEventMulticaster bean 中。
9. 留给子类来初始化其他的 bean。
10. 在所有注册的 bean 中查找 listener bean,注册到消息广播器中。
11. 初始化剩下的单实例(非惰性的)。
12. 完成刷新过程。通知生命周期处理器 lifecycleProcessor 刷新过程,同时发出 ContextRefreshEvent 通知别人。

6.3 环境准备

 对应 1. 初始化前的准备工作

 prepareRefresh()
public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
	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());
			}
		}

		// 留给子类覆盖
		// 探讨作用:用户可以根据需要重写该方法,并在方法中进行个性化的属性处理及设置。
		initPropertySources();

		// 验证需要的属性文件是否都已经放入环境中
		// 探讨作用:可以实现对属性进行验证的逻辑,大概步骤如下
		// 1. 自定义 ClassPathXmlApplicationContext 的子类 MyClassPathXmlApplicationContext
		// 2. 重写 initPropertySources()方法,添加验证代码:getEnvironment().setRequiredProperties("VAR");
		// 3. new MyClassPathXmlApplicationContext("text.xml");
		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<>();
	}
}

 其中关注点如下。

  • initPropertySources。用户可以根据需要重写该方法,并在方法中进行个性化的属性处理及设置。
  • validateRequiredProperties。可以实现自定义对属性进行验证的逻辑。

6.4 加载 BeanFactory

 对应 2. 初始化 BeanFactory,并进行 XML 文件读取。

 obtainFreshBeanFactory()
public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		// 初始化 BeanFactory,并进行 XML 文件读取,并将得到的 BeanFactory 记录在当前实例的属性中
		refreshBeanFactory();
		// 返回当前实体的 beanFactory 属性
		return getBeanFactory();
	}
}

public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
	protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			// 1. 创建 DefaultListableBeanFactory。
			DefaultListableBeanFactory beanFactory = createBeanFactory();

			// 2. 指定序列化 ID。
			// 为了序列化指定 id,如果需要的话,让这个 BeanFactory 从 id 反序列化到 BeanFactory 对象
			beanFactory.setSerializationId(getId());

			// 3. 定制 BeanFactory。
			// 定制 beanFactory,设置相关属性,包括是否允许覆盖同名称的不同定义的对象以及循环依赖
			// 以及 @Autowired 和 @Qualifier 注解解析器 QualifierAnnotationAutowireCandidateResolver
			// 对应的解析方法是 QualifierAnnotationAutowireCandidateResolver.getSuggestedValue(descriptor);
			customizeBeanFactory(beanFactory);

			// 4. 加载 BeanDefinition。
			// 初始化 DocumentReader,并进行 XML 文件读取及解析
			// --> ClassPathXmlApplicationContext --> AbstractXmlApplicationContext
			loadBeanDefinitions(beanFactory);

			// 5. 使用全局变量记录 BeanFactory 类实例。
			this.beanFactory = beanFactory;
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}
}

 经过这个函数后 ApplicationContext 就已经拥有了 BeanFactory 的全部功能,主要逻辑如下。

  1. 创建 DefaultListableBeanFactory。

 DefaultListableBeanFactory 是容器的基础,必须首先实例化。
2. 指定序列化 ID。
3. 定制 BeanFactory。
4. 加载 BeanDefinition。
5. 使用全局变量记录 BeanFactory 类实例。

 注意:因为方法内的 DefaultListableBeanFactory 类型的变量 beanFactory 是函数内的局部变量,所以要使用全局变量记录解析结果。

6.4.1 定制 BeanFactory

 customizeBeanFactory()
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
	protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
		// 如果不为空,设置给 beanFactory 对象相应属性:是否允许覆盖同名称的不同定义的对象
		if (this.allowBeanDefinitionOverriding != null) {
			beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
		}
		// 如果不为空,设置给 beanFactory 对象相应属性:是否允许 bean 之间的循环依赖
		if (this.allowCircularReferences != null) {
			beanFactory.setAllowCircularReferences(this.allowCircularReferences);
		}
		// 老版本这里有下面一行代码,当前版本没有
		// beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver())
	}
}

 其中关注点如下。
 前面说 bean 加载部分提过的代码 com.stu.spring.context.chapter05.circle.DisabledCircleSingletonTest,就是用子类覆盖的方式定制了 BeanFactory,以及类似自定义加密逻辑也可以用这种方式实现。

6.4.2 加载 BeanDefinition

 loadBeanDefinitions()
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// 为指定的 beanFactory 创建 beanDefinitionReader
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// 1. 为 beanDefinitionReader 进行环境变量的设置
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		// 2. 对 beanDefinitionReader 设置,并覆盖
		initBeanDefinitionReader(beanDefinitionReader);

		// 3. 配置文件的读取,复用了前面说的第 2 部分容器的基本实现相关的代码。
		loadBeanDefinitions(beanDefinitionReader);
	}
	
	protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			reader.loadBeanDefinitions(configResources);
		}
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
	}
}

 经过此步骤,类型 DefaultListableBeanFactory 的变量 baenFactory 已经包含了所有解析好的配置。

6.5 功能扩展

 对应 3. 对 BeanFactory 进行各种功能填充

 prepareBeanFactory()
public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// 设置 beanFactory 的 classLoader 为当前 context 的 classLoader
		beanFactory.setBeanClassLoader(getClassLoader());

		// 1. 增加对 SpEL 语言的支持。
		// 设置 beanFactory 的表达式语言处理器,Spring3 增加了表达式语言的支持,
		// 默认可以使用 #{bean.xxxx} 的形式来调用相关属性值
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));

		// 2. 增加对属性编辑器的支持。
		// 为 beanFactory 增加了一个默认的 propertyEditor,这个主要是对 bean 的属性等设置管理的一个工具
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// 3. 增加对一些内置类,比如 EnvironmentAware、MessageSourceAware 的信息注入。
		// 添加 BeanPostProcessor
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

		// 4. 设置了依赖功能可忽略的接口。
		// 设置了几个忽略自动装配的接口
		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. 注册一些固定依赖的属性。
		// 设置了几个自动装配的特殊规则
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

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

		// 6. 增加 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()));
		}

		// 7. 将相关环境变量及属性注册以单例模式注册。
		// 添加默认的系统环境 bean
		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());
		}
	}
}

 进入 prepareBeanFactory 方法前,Spring 已完成对配置的解析,这里开始了 ApplicationContext 在功能上的拓展。
 prepareBeanFactory 方法主要逻辑如下。

  1. 增加对 SpEL 语言的支持。
  2. 增加对属性编辑器的支持。
  3. 增加对一些内置类,比如 EnvironmentAware、MessageSourceAware 的信息注入。
  4. 设置了依赖功能可忽略的接口。
  5. 注册一些固定依赖的属性。
  6. 增加 AspectJ 的支持。
  7. 将相关环境变量及属性注册以单例模式注册。

6.5.1 增加 SpEL 语言的支持

 增加 SpEL 语言的支持

 Spring 表达式语言全称为 Spring Expression Language。缩写为 SpEL,能在运行时构建复杂表达式、存取对象图属性、对象方法调用等,并且能与 Spring 功能完美整合。SpEL 是单独模块,只依赖于 core 模块,不依赖于其他模块,可以单独使用。
 注册代码为 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()))。
 上面注册好了语言解析器后,我们再研究下什么时候调用这个解析器解析。
 我们在讲解 Spring 在 bean 进行初始化的时候会有属性填充的一步,而在这一步中 Spring 会调用 AbstractAutowireCapableBeanFactory 类的 applyPropertyValues 函数来完成功能。该函数会通过 BeanDefinitionValueResolver 类型实例 valueResolver 来进行属性的解析,里面用到了 AbstractBeanFactory 中的 evaluateBeanDefinitionString 方法去完成 SpEL 的解析。
 通过查看 evaluateBeanDefinitionString 方法的调用层次可以看出,应用语言解析器的调用主要是在解析依赖注入 bean 的时候,以及在完成 bean 的初始化和属性获取后进行属性填充的时候。

6.5.2 增加属性注册编辑器

 在 Spring DI 注入的时候可以把普通属性注入进来,但是像 Date 类型就无法被识别。将 String 类型的注入 Date 类型中,Spring 提供了两种方式。

1. 使用自定义属性编辑器

 详见代码 com.stu.spring.context.chapter06.propertyeditor.CustomDatePropertyTest

2. 注册 Spring 自带的属性编辑器 CustomDateEditor  详细代码同上,只不过不需要我们自定义 CustomDatePropertyEditor 了。  回到 Spring 源码部分 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()))。
 ResourceEditorRegistrar.registerCustomEditors 调用链分析

 这里代码调用涉及到前面说的 bean 加载逻辑,先将调用链理清楚,调用链如下

// AbstractBeanFactory
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)

return createBean(beanName, mbd, args);

// --> AbstractAutowireCapableBeanFactory
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

instanceWrapper = createBeanInstance(beanName, mbd, args);

// 这里有多个分支逻辑,举部分例子
return autowireConstructor(beanName, mbd, null, null); // 构造函数自动注入
return instantiateBean(beanName, mbd); // or 使用默认构造函数构造

// --> ConstructorResolver 触发对应的 initBeanWrapper 方法
beanFactory.initBeanWrapper(bw); // or initBeanWrapper(bw);

// --> AbstractBeanFactory
registerCustomEditors(bw); // 在这里注册了属性编辑器

 这里调用链比较长,我们没必要死记,可以按如下步骤跟踪到调用栈,找到 initBeanWrapper 方法后就是我们前面聊过的 bean 加载的逻辑了。

  1. 打开 IDEA 的 Structure 窗口,右击 ResourceEditorRegistrar.registerCustomEditors,点击 findUsages,找到 AbstractBeanFactory.registerCustomEditors 方法。
  2. 右击 AbstractBeanFactory.registerCustomEditors,点击 findUsages,找到有一个选项 AbstractBeanFactory.initBeanWrapper 方法。
 registerCustomEditors()

 重点关注下 ResourceEditorRegistrar.registerCustomEditors 方法。

public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
	public void registerCustomEditors(PropertyEditorRegistry registry) {
		ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.propertyResolver);

		// 调用 doRegisterEditor 注册属性编辑器
		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));
		}
	}
}
  1. 调用了 doRegisterEditor 方法。
  2. doRegisterEditor 方法调用了 registry.registerCustomEditor(requiredType, editor);。

 doRegisterEditor 方法和我们对应的测试代码实现功能都类似。因此 ResourceEditorRegistrar.registerCustomEditors 方法是注册了一系列的常用类型的属性编辑器。

 Spring 默认注册的属性编辑器

 Spring 中用于封装 bean 的是 BeanWrapper 类型,而它又间接继承了 PropertyEditorRegistry 类型,对于 BeanWrapper 在 Spring 中的默认实现是 BeanWrapperImpl,而 BeanWrapperImpl 除了实现 BeanWrapper 接口外还继承了 PropertyEditorRegistrySupport,在 PropertyEditorRegistrySupport 中有 createDefaultEditors 方法,在其中创建了一系列常用的属性编辑器。如果我们定义的 bean 中的某个属性的类型不在上面的常用配置中的话,才需要我们进行个性化属性编辑器的注册。

public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
	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);
		}
	}
}

6.5.3 添加 ApplicationContextAwareProcessor 处理器

添加 ApplicationContextAwareProcessor 处理器

 ApplicationContextAwareProcessor 实现 BeanPostProcessor 接口,前面有了解过,在 bean 实例化的时候,也就是 Spring 激活 bean 的 init-method 的前后,会调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法和 postProcessAfterInitialization 方法。
 ApplicationContextAwareProcessor 对于 postProcessAfterInitialization 方法没有做处理,重点看下 postProcessBeforeInitialization 方法源码。

postProcessBeforeInitialization

 postProcessBeforeInitialization 方法中调用了 invokeAwareInterfaces,实现这些 Aware 接口的 bean 在被初始化之后可以取得一些对应的资源。

class ApplicationContextAwareProcessor implements BeanPostProcessor {
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
				bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
				bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
			return bean;
		}

		AccessControlContext acc = null;

		if (System.getSecurityManager() != null) {
			acc = this.applicationContext.getBeanFactory().getAccessControlContext();
		}

		if (acc != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				// 实现这些 Aware 接口的 bean 在被初始化之后可以取得一些对应的资
				invokeAwareInterfaces(bean);
				return null;
			}, acc);
		}
		else {
			invokeAwareInterfaces(bean);
		}

		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 ApplicationContextAware) {
			((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
		}
	}
}

6.5.4 设置忽略依赖

 当 Spring 将 ApplicationContextAwareProcessor 注册后,那么在 invokeAwareInterfaces 方法中间接调用的 Aware 类以及不是普通的 bean 了,如 ResourceLoaderAware、ApplicationEventPublisherAware 等,那么当然需要在 Spring 做 bean 的依赖注入的时候忽略它们。

6.5.5 注册依赖

 和忽略依赖功能对应,提供了注册依赖的功能(必须的,不然怎么注册呢)。
 当注册了依赖解析后,例如当注册了对 BeanFactory.class 的解析依赖后,当 bean 的属性注入的时候,一旦检测到属性为 BeanFactory 类型便会将 beanFactory 的实例注入进去。

6.6 BeanFactory 的后处理

 对应 5. 激活各种 BeanFactory 处理器

激活各种 BeanFactory 处理器

 BeanFactory 是 Spring 容器功能的基础,用于存放所有已经加载的 bean,为了保证程序上的高可扩展性,Spring 针对 BeanFactory 做了大量的扩展,包括我们熟知的 PostProcessor。

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		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()));
		}
	}
}

6.6.1 激活注册的 BeanFactoryPostProcessor

BeanFactoryPostProcessor 的用法

 BeanFactoryPostProcessor 接口和 BeanPostProcessor 类似,可以对 bean 的定义进行处理。但是它是容器级的,如果想改变实际的 bean 实例,最好使用 BeanPostProcessor。BeanFactoryPostProcessor 仅仅对此容器中的 bean 进行后置处理。  Spring IOC 容器允许 BeanFactoryPostProcessor 在容器实际实例化任何其他的 bean 之前读取配置元数据,并有可能修改它。还可以配置多个 BeanFactoryPostProcessor,以及通过设置 order 属性来控制 BeanFactoryPostProcessor 的执行次序。
 我们看下两个典型的应用。

 1. BeanFactoryPostProcessor 的典型应用:PropertyPlaceholderConfigurer

 详细示例代码见 com.stu.spring.context.chapter06.beanfactorpp.PlaceholderTest

TIP

 这里需注意下,Spring 是怎么知道要从这个 mesHandle 中获取配置信息的呢?
 是因为 PropertyPlaceholderConfigurer 间接继承了 BeanFactoryPostProcessor 接口。当 Spring 加载任何实现了这个接口的 bean 的配置时,都会在 bean 工厂载入所有 bean 的配置之后执行 postProcessBeanFactory 方法。在 PropertyResourceConfigurer 类中实现了 postProcessBeanFactory 方法,在方法中先后调用了 mergeProperties、convertProperties、processProperties 这 3 个方法,分别得到配置,将得到的配置转换为合适的类型,最后将配置内容告知 BeanFactory。BeanFactory 会在实例化任何 bean 之前获得配置信息,从而能够正确解析 bean 描述文件的变量引用。

 2. 使用自定义 BeanFactoryPostProcessor

 我们实现一个 BeanFactoryPostProcessor,做一个属性黑名单的功能,在黑名单名称列表中直接隐藏信息。
 详细示例代码见 com.stu.spring.context.chapter06.beanfactorpp,注意 PropertyBlackNameBeanFactoryPostProcessor.postProcessBeanFactory 方法只会执行一次。

 3. 激活 BeanFactoryPostProcessor

 了解用法后我们研究下 BeanFactoryPostProcessor 的调用过程。

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

		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
		Set<String> processedBeans = new HashSet<>();

		// 对 BeanDefinitionRegistry 类型的处理
		// BeanDefinitionRegistryPostProcessor 只对 BeanDefinitionRegistry 类型的 ConfigurableListableBeanFactory 有效。
		// 如果不是的话,直接处理 BeanFactoryPostProcessor
		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			// BeanDefinitionRegistryPostProcessor
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

			// 1. 对于硬编码注册的后处理器的处理,即处理由 AbstractApplicationContext.addBeanFactoryPostProcessor 添加的 BeanFactoryPostProcessor。
			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				// BeanDefinitionRegistryPostProcessor 有 BeanFactoryPostProcessor 和 BeanDefinitionRegistryPostProcessor 两个特性,都需要执行
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					// 对于 BeanDefinitionRegistryPostProcessor 类型,在 BeanFactoryPostProcessor 的基础上还有自己定义的方法,需要先调用
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}
				else {
					// 记录常规 BeanFactoryPostProcessor
					regularPostProcessors.add(postProcessor);
				}
			}

			/**
			 * 配置注册的后处理器,有按照顺序配置执行
			 */
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			// 2. 记录并激活 BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry 后处理器,主要分 3 步执行。
			// 2.1 调用实现了 PriorityOrdered 接口的 BeanDefinitionRegistryPostProcessors。
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			// 注册实现了 PriorityOrdered 接口的 BeanDefinitionRegistryPostProcessors,然后重置 currentRegistryProcessors
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();

			// 2.2 调用实现了 Ordered 接口的 BeanDefinitionRegistryPostProcessors。
			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);
			// 注册实现了 Ordered 接口的 BeanDefinitionRegistryPostProcessors,然后重置 currentRegistryProcessors
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();

			// 2.3 调用其他所有无序的 BeanDefinitionRegistryPostProcessors。
			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();
			}

			// 3. 统一激活 postProcessBeanFactory.postProcessBeanFactory 方法。
			// 配置的 BeanDefinitionRegistryPostProcessor
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			// 常规 BeanFactoryPostProcessor
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

		else {
			// 对 BeanFactoryPostProcessor 的处理,直接调用 postProcessBeanFactory 的 postProcessBeanFactory 回调方法
			invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
		}

		// 4. 普通 beanFactory 处理。
		// 对于配置中读取的 BeanFactoryPostProcessor 的处理
		// Do not initialize FactoryBeans here: We need to leave all regular beans
		// uninitialized to let the bean factory post-processors apply to them!
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

		// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		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)) {
				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// 按照优先级进行排序
		// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String postProcessorName : orderedPostProcessorNames) {
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		// 按照 order 排序
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// 无序,直接调用
		// Finally, invoke all other BeanFactoryPostProcessors.
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		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();
	}
}

 PostProcessorRegistrationDelegate 的 invokeBeanFactoryPostProcessors 的主要逻辑如下。

    1. 对于硬编码注册的后处理器的处理,即处理由 AbstractApplicationContext.addBeanFactoryPostProcessor 添加的 BeanFactoryPostProcessor。
    1. 记录并激活 BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry 后处理器,主要分 3 步执行。
    • 2.1 调用实现了 PriorityOrdered 接口的 BeanDefinitionRegistryPostProcessors。
    • 2.2 调用实现了 Ordered 接口的 BeanDefinitionRegistryPostProcessors。
    • 2.3 调用其他所有无序的 BeanDefinitionRegistryPostProcessors。
    1. 统一激活 postProcessBeanFactory.postProcessBeanFactory 方法。
    1. 普通 beanFactory 处理。

 需要注意下:

  • BeanDefinitionRegistryPostProcessor 只对 BeanDefinitionRegistry 类型的 ConfigurableListableBeanFactory 有效。如果不是的话,直接处理 BeanFactoryPostProcessor 了。
  • 对于硬编码方式手动添加的后处理器是不需要做任何排序的,但是在配置文件中读取的处理器,Spring 并不保证读取的顺序。所以,为了保证用户的调用顺序的要求,Spring 对于后处理器的调用支持按照 PriorityOrdered 或者 Ordered 的顺序调用。

6.6.2 注册 BeanPostProcessor

 对应 6. 注册拦截 bean 创建的 bean 处理器

注册 BeanPostProcessor
public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
	protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
	}
}

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

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

		/**
		 * BeanPostProcessorChecker 是一个普通的信息打印,可能会有些情况
		 * 当 Spring 的配置中的后处理器还没有被注册就已经开始了 bean 的初始化时,便会打印出 BeanPostProcessorChecker 中设定的消息。
		 */
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

		// 使用 PriorityOrdered 保证顺序
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		// MergedBeanDefinitionPostProcessor
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		// 使用 Ordered 保证顺序
		List<String> orderedPostProcessorNames = new ArrayList<>();
		// 无序 BeanPostProcessor
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				// 连续的两次 add 没有重复添加,里面是移除后再加入的,保证了唯一性
				priorityOrderedPostProcessors.add(pp);
				if (pp instanceof MergedBeanDefinitionPostProcessor) {
					internalPostProcessors.add(pp);
				}
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// 1. 注册所有实现 PriorityOrdered 的 BeanPostProcessor
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// 2. 注册所有实现 Ordered 的 BeanPostProcessor
		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);
			}
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);

		// 3. 注册所有无序的 BeanPostProcessor
		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);
			}
		}
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

		// 4. 注册所有 MergedBeanDefinitionPostProcessor 类型的 BeanPostProcessor,并非重复注册
		// PS: registerBeanPostProcessors 里面是先 remove,再 add 的,因此没有重复注册 internalPostProcessors 的问题
		sortPostProcessors(internalPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		// 添加 ApplicationListener 探测器
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}
}

 默认 BeanFactory 及其大部分子类都没有实现后处理器的自动注册,所以在调用的时候如果没有手动注册其实是不能使用的。但是在 ApplicationContext 中已添加了自动注册功能。使用示例见 com.stu.spring.context.chapter06.beanpostprocessor.CustomBeanPostProcessorTest

BeanPostProcessor 处理两种情况

TIP

 对于 BeanPostProcessor 的处理与 BeanFactoryPostProcessor 的处理极为相似,但是有两点不一样:

  1. 通过硬编码方式的处理。
  2. 通过配置文件方式的处理。

 BeanPostProcessor 的处理中只考虑了配置文件的方式而不考虑硬编码的方式原因如下。
 BeanFactoryPostProcessor 的处理,不但要实现注册功能,还要实现对后处理器的激活操作,所以需要载入配置中的定义,并进行激活;而对于 BeanPostProcessor 并不需要马上调用。换句话说,硬编码的方式实现的功能是将后处理器提取并调用,这里并不需要调用,因此不需要考虑硬编码的方式了。

6.6.3 初始化消息资源

 对应 7. 为上下文初始化 Message 源

前述

 JDK 的 java.util 包中提供了几个支持本地化的格式化操作工具类:NumberFormat、DateFormat、MessageFormat,而在 Spring 中的国际化资源操作也是对于这些类的封装操作,JDK 具体使用示例代码见 com.stu.spring.context.chapter06.message.JavaMessageTest
 Spring 的 MessageSource 类图结构如下。
MessageSource.png

 几个重要的类说明如下:

  • MessageSource:访问国际化信息的接口。
  • ResourceBundleMessageSource:基于 Java 的 ResourceBundle 基础类实现,允许仅通过资源名加载国际化资源。
  • ReloadableResourceBundleMessageSource:同上,额外提供了定时刷新功能。
  • StaticMessageSource:主要用于程序测试,它允许通过编程的方式提供国际化信息。
  • DelegatingMessageSource:为方便操作父 MessageSource 而提供的代理类。

 使用示例见 com.stu.spring.context.chapter06.message.MessagesTest
 注意中文转码可以使用 cmd 命令 native2ascii -encoding gbk message_zh_CN.properties

initMessageSource()
public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
	protected void initMessageSource() {
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		// 硬编码规定了自定义资源文件必须为 messageSource,否则便会获取不到自定义资源配置。
		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 {
			// 如果用户并没有定义配置文件,那么使用临时的 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 + "]");
			}
		}
	}
}

 配置好后,后续就可以通过 AbstractApplicationContext.getMessage(...) 调用了。

6.6.4 初始化 ApplicationEventMulticaster

 对应 8. 初始化应用消息广播器

前述

 Spring 监听事件的用法见示例代码 com.stu.spring.context.chapter06.event

registerListeners
public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
	protected void initApplicationEventMulticaster() {
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		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 {
			// SimpleApplicationEventMulticaster 是 ApplicationEventMulticaster 子类
			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() + "]");
			}
		}
	}
}

public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

	/**
	 * 广播事件方法,广播的时候这里来通知进行监听器的处理
	 */
	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);
			}
		}
	}
}
  1. 如果用户自定义了事件广播器,那么使用用户自定义的事件广播器。
  2. 如果用户没有自定义事件广播器,那么使用默认的 ApplicationEventMulticaster

ApplicationEventMulticaster 中有 multicastEvent,可以通过这个方法来广播事件,遍历所有监听器。

6.6.5 注册监听器

 对应 10. 在所有注册的 bean 中查找 listener bean,注册到消息广播器中

registerListeners()
public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
	protected void registerListeners() {
		// 硬编码方式注册的监听器处理
		for (ApplicationListener<?> listener : getApplicationListeners()) {
			getApplicationEventMulticaster().addApplicationListener(listener);
		}

		// 配置文件注册的监听器处理
		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 (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
			for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
				getApplicationEventMulticaster().multicastEvent(earlyEvent);
			}
		}
	}
}

6.7 初始化非延迟加载单例

 对应 11. 初始化剩下的单实例(非惰性的)

finishBeanFactoryInitialization()
public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
	protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// 完成 BeanFactory 的初始化工作,其中包括 ConversionService 的设置、配置冻结以及非延迟加载的 bean 初始化工作。
		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 BeanFactoryPostProcessor
		// (such as a PropertySourcesPlaceholderConfigurer 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);

		// 冻结所有的 bean 定义,说明注册的 bean 定义将不被修改或任何进一步的处理
		beanFactory.freezeConfiguration();

		// 初始化剩下的单实例(非惰性的)
		beanFactory.preInstantiateSingletons();
	}
}

 finishBeanFactoryInitialization 主要功能是完成 BeanFactory 的初始化工作,其中包括 ConversionService 的设置、配置冻结以及非延迟加载的 bean 初始化工作。

 1. ConversionService 的设置

 之前使用过自定义类型转换器从 String 转 Date 的方式,Spring 还提供了另一种转换方式:使用 Converter,其使用示例代码见 com.stu.spring.context.chapter06.finishbf.String2DateConverterTest

 2. 冻结配置

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

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
	public void freezeConfiguration() {
		this.configurationFrozen = true;
		this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
	}
}
 3. 初始化非延迟加载

ApplicationContext 实现的默认行为就是在启动时将所有单例 bean 提前进行实例化。具体过程代码入口如下。

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
	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()) {
				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) {
							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) {
				SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}
}

6.8 finishRefresh

 对应 12. 完成刷新过程

finishRefresh

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

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
	protected void finishRefresh() {
		// Clear context-level resource caches (such as ASM metadata from scanning).
		clearResourceCaches();

		// 1. initLifecycleProcessor。
		// Initialize lifecycle processor for this context.
		initLifecycleProcessor();

		// 2. onRefresh。
		// Propagate refresh to lifecycle processor first.
		getLifecycleProcessor().onRefresh();

		// 3. publishEvent。
		// Publish the final event.
		publishEvent(new ContextRefreshedEvent(this));

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

  1. publishEvent。

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

 1. initLifecycleProcessor

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

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
	protected void initLifecycleProcessor() {
		// 初始化 LifecycleProcessor
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		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() + "]");
			}
		}
	}
}
 2. onRefresh

 启动所有实现了 Lifecycle 接口的 bean。

public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactoryAware {
	public void onRefresh() {
		startBeans(true);
		this.running = true;
	}

	private void startBeans(boolean autoStartupOnly) {
		Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
		// phases 缓存 bean
		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);
			}
		});
		// 遍历 phases,调用 start 方法
		if (!phases.isEmpty()) {
			List<Integer> keys = new ArrayList<>(phases.keySet());
			Collections.sort(keys);
			for (Integer key : keys) {
				phases.get(key).start();
			}
		}
	}
}
 3. publishEvent
public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
	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);
			}
		}
	}
}
Last Updated 3/1/2025, 9:47:40 PM