Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;

static {
	applicationContext = new ClassPathXmlApplicationContext("bean.xml");
}

BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanFactory的功能相似,都是用于向IOC中加载Bean的。由于ApplicationConext的功能是多于BeanFactory的,所以在日常使用中,建议直接使用ApplicationConext即可。在 ApplicationConext的构造方法中,主要做了两个事情:

① 设置配置的加载路径;

② 执行ApplicationConext中,所有功能的初始化操作;

/**
 * 创建一个新的ClassPathXmlApplicationContext,从给定的XML文件中加载定义。
 */
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
	this(configLocations, refresh, null);
}

/**
 * 使用给定的父类创建一个新的ClassPathXmlApplicationContext,从给定的XML文件中加载定义。
 */
// eg1:configLocations=["bean.xml"],refresh=true,parent=null
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
	super(parent);

	/** 1:设置配置路径 */
	setConfigLocations(configLocations); // eg1:configLocations=["bean.xml"]

	/** 2:执行初始化操作 */
	if (refresh) // eg1:true
		refresh();
}

setConfigLocations 设置配置加载路径

该方法逻辑不多,主要就是为应用上下文AbstractRefreshableConfigApplicationContext 类设置配置路径(String[] configLocations),源码如下所示:

/**
 * 为应用上下文(application context)设置配置路径(config locations)
 */
// eg1:locations=["bean.xml"]
public void setConfigLocations(@Nullable String... locations) {
	if (locations != null) {
		Assert.noNullElements(locations, "Config locations must not be null");
		this.configLocations = new String[locations.length];

		/** 如果路径中包含特殊符号(如:${var}),那么在resolvePath方法中会搜寻匹配的系统变量并且进行替换操作 */
		for (int i = 0; i < locations.length; i++)
			this.configLocations[i] = resolvePath(locations[i]).trim(); // eg1:configLocations=["bean.xml"]  // xml配置文件所在路径
	}
	else
		this.configLocations = null;
}
/**
 * 解析给定的路径,必要时用相应的环境属性值替换占位符。应用于配置位置。
 */
// eg1:path="bean.xml"
protected String resolvePath(String path) {
	return getEnvironment().resolveRequiredPlaceholders(path);
}
// eg1:text="bean.xml"
@Override
public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
	// eg1:propertyResolver=AbstractPropertyResolver
	return this.propertyResolver.resolveRequiredPlaceholders(text);
}
// eg1:text="bean.xml"
@Override
public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
	if (this.strictHelper == null) // eg1:strictHelper=null
		this.strictHelper = createPlaceholderHelper(false);
	return doResolvePlaceholders(text, this.strictHelper);
}
/**
 * 创建PropertyPlaceholderHelper实例对象
 */
private PropertyPlaceholderHelper createPlaceholderHelper(boolean ignoreUnresolvablePlaceholders) {
	/** placeholderPrefix = "${", placeholderSuffix = "}", valueSeparator = ":" */
	return new PropertyPlaceholderHelper(this.placeholderPrefix, this.placeholderSuffix,
			this.valueSeparator, ignoreUnresolvablePlaceholders);
}

// eg1:text="bean.xml", helper=PropertyPlaceholderHelper
private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper) {
	return helper.replacePlaceholders(text, this::getPropertyAsRawString);
}
/**
 * 将格式${name}中的所有占位符替换为提供的PlaceholderResolver的返回值。
 */
// eg1:value="bean.xml"
public String replacePlaceholders(String value, PlaceholderResolver placeholderResolver) {
	Assert.notNull(value, "'value' must not be null");
	return parseStringValue(value, placeholderResolver, null);
}

// eg1:value="bean.xml",visitedPlaceholders=null
protected String parseStringValue(String value, PlaceholderResolver placeholderResolver, @Nullable Set<String> visitedPlaceholders) {
	int startIndex = value.indexOf(this.placeholderPrefix);
	// eg1:startIndex=-1
	if (startIndex == -1) return value; // eg1:return "bean.xml"

	StringBuilder result = new StringBuilder(value);
	while (startIndex != -1) {
		int endIndex = findPlaceholderEndIndex(result, startIndex);
		if (endIndex != -1) {
			String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex);
			String originalPlaceholder = placeholder;
			if (visitedPlaceholders == null) {
				visitedPlaceholders = new HashSet<>(4);
			}
			if (!visitedPlaceholders.add(originalPlaceholder)) {
				throw new IllegalArgumentException(
						"Circular placeholder reference '" + originalPlaceholder + "' in property definitions");
			}
			// Recursive invocation, parsing placeholders contained in the placeholder key.
			placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
			// Now obtain the value for the fully resolved key...
			String propVal = placeholderResolver.resolvePlaceholder(placeholder);
			if (propVal == null && this.valueSeparator != null) {
				int separatorIndex = placeholder.indexOf(this.valueSeparator);
				if (separatorIndex != -1) {
					String actualPlaceholder = placeholder.substring(0, separatorIndex);
					String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length());
					propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder);
					if (propVal == null) {
						propVal = defaultValue;
					}
				}
			}
			if (propVal != null) {
				// Recursive invocation, parsing placeholders contained in the
				// previously resolved placeholder value.
				propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);
				result.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);
				if (logger.isTraceEnabled()) {
					logger.trace("Resolved placeholder '" + placeholder + "'");
				}
				startIndex = result.indexOf(this.placeholderPrefix, startIndex + propVal.length());
			}
			else if (this.ignoreUnresolvablePlaceholders) {
				// Proceed with unprocessed value.
				startIndex = result.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length());
			}
			else {
				throw new IllegalArgumentException("Could not resolve placeholder '" +
						placeholder + "'" + " in value \"" + value + "\"");
			}
			visitedPlaceholders.remove(originalPlaceholder);
		}
		else {
			startIndex = -1;
		}
	}
	return result.toString();
}

refresh 初始化工作

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

/**
 * 返回静态指定的ApplicationListeners的列表
 */
public Collection<ApplicationListener<?>> getApplicationListeners() {
	return this.applicationListeners;
}

@Override
public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
		/** 1:为refresh操作做提前的准备工作 */
		prepareRefresh();

		/** 2:获得beanFactory实例对象 */
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		/** 3:准备用于此上下文的beanFactory */
		prepareBeanFactory(beanFactory);
		try {
			postProcessBeanFactory(beanFactory); // 允许在上下文子类中对BeanFactory进行后置处理(空方法,可由子类实现)
			StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");

			/** 4:激活各种BeanFactoryPostProcessor的后置处理器 */
			invokeBeanFactoryPostProcessors(beanFactory);

			/** 5:注册各种Bean的后置处理器,在getBean时才会被调用 */
			registerBeanPostProcessors(beanFactory);
			beanPostProcess.end();

			/** 6:为上下文初始化消息源(即:国际化处理)*/
			initMessageSource();

			/** 7:为上下文初始化应用事件广播器 */
			initApplicationEventMulticaster();
			onRefresh(); // 初始化特定上下文子类中的其他特殊bean(空方法,可由子类实现)

			/** 8:在所有注册的bean中查找listener bean,并注册到消息广播器中 */
			registerListeners();

			/** 9:初始化剩下的单例(非惰性non-lazy-init)*/
			finishBeanFactoryInitialization(beanFactory);

			/** 10:完成refresh,通知lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知 */
			finishRefresh();
		} catch (BeansException ex) {……
		} finally {……
		}
	}
}

 /** 1:为refresh操作做提前的准备工作 */ 

prepareRefresh主要是为了容器进行刷新做准备,它实现的步骤如下:

① 设置容器的启动时间。

② 设置活跃状态为true。

③ 设置关闭状态为false

④ 获取Environment对象,并加载当前系统的属性值到Environment对象中。

⑤ 准备监听器和事件的集合对象,默认为空的集合。

/**
 * 为刷新准备这个上下文,设置它的启动日期和活动标志,以及执行任何属性源的初始化。
 */
protected void prepareRefresh() {
	this.startupDate = System.currentTimeMillis(); // 设置容器启动的时间
	this.closed.set(false); // 容器的关闭标志位
	this.active.set(true); // 容器的激活标志位
	initPropertySources(); // 留给子类覆盖,初始化属性资源(空方法)

	/** 创建并获取环境对象,验证需要的属性文件是否都已经放入环境中 */
	getEnvironment().validateRequiredProperties();

	// 如果为空,则以applicationListeners为准
	if (this.earlyApplicationListeners == null) // eg1:earlyApplicationListeners=null
		this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners); // eg1:applicationListeners.size()=0
	// 如果不等于空,则清空applicationListeners,以earlyApplicationListeners为准
	else {
		this.applicationListeners.clear();
		this.applicationListeners.addAll(this.earlyApplicationListeners);
	}
	// 创建刷新前的监听事件集合
	this.earlyApplicationEvents = new LinkedHashSet<>();
}

 validateRequiredProperties():

@Override
public void validateRequiredProperties() {
	MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
	for (String key : this.requiredProperties) { // eg1: requiredProperties.size()=0
		if (this.getProperty(key) == null)
			ex.addMissingRequiredProperty(key);
	}
	if (!ex.getMissingRequiredProperties().isEmpty()) // eg1:ex.getMissingRequiredProperties().size()=0
		throw ex;
}

/** 2:obtainFreshBeanFactory 获得beanFactory实例对象 */

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

/**
 * 告诉子类刷新内部bean工厂。
 */
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
	/** 1:初始化BeanFactory,并加载bean的配置文件 */
	refreshBeanFactory(); // eg1:AbstractRefreshableApplicationContext#refreshBeanFactory()

	/** 2:获得BeanFactory */
	return getBeanFactory(); // eg1:AbstractRefreshableApplicationContext#getBeanFactory()
}

obtainFreshBeanFactory() 的 1:初始化BeanFactory,并加载bean的配置文件

/**
 * 此实现执行此上下文的底层bean工厂的实际刷新,关闭前一个bean工厂(如果有的话)并为上下文生命周期的下一阶段初始化一个新的bean工厂。
 */
@Override
protected final void refreshBeanFactory() throws BeansException {
	/** 1: 如果存在BeanFactory,则执行清理操作(即:删除Bean及关闭BeanFactory) */
	if (hasBeanFactory()) { // eg1:false
		destroyBeans();
		closeBeanFactory();
	}
	try {
		/** 2:创建DefaultListableBeanFactory实例对象 */
		DefaultListableBeanFactory beanFactory = createBeanFactory();

		// eg1:(getId()="org.springframework.context.support.ClassPathXmlApplicationContext@2bec854f"
		beanFactory.setSerializationId(getId());

		/** 3:定制此上下文使用的内部bean工厂,向BeanFactory设置setAllowBeanDefinitionOverriding和setAllowCircularReferences */
		customizeBeanFactory(beanFactory);

		/** 4:加载BeanDefinition */
		loadBeanDefinitions(beanFactory); // eg1:AbstractXmlApplicationContext#loadBeanDefinitions(beanFactory)

		this.beanFactory = beanFactory;
	}
	catch (IOException ex) {
		throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
	}
}

1: 如果存在BeanFactory,则执行清理操作(即:删除Bean及关闭BeanFactory) 

/**
 * 确定此上下文当前是否持有bean工厂,即至少被刷新过一次且尚未关闭。
 */
protected final boolean hasBeanFactory() {
	return (this.beanFactory != null);  // 开始的时候beanFactory为空
}

2:创建DefaultListableBeanFactory实例对象:new一个

/**
 * 为此上下文创建一个内部bean工厂。每次尝试refresh()时都会调用。
 * 默认实现会创建一个DefaultListableBeanFactory,其中,getInternalParentBeanFactory()是这个上下文的父bean工厂。
 * 可以在子类中重写,例如自定义DefaultListableBeanFactory的设置。
 */
protected DefaultListableBeanFactory createBeanFactory() {
	return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}

3:定制此上下文使用的内部bean工厂,向BeanFactory设置setAllowBeanDefinitionOverriding和setAllowCircularReferences

/**
 * 定制此上下文使用的内部bean工厂,向BeanFactory设置setAllowBeanDefinitionOverriding和setAllowCircularReferences
 */
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
	if (this.allowBeanDefinitionOverriding != null) // eg1:allowBeanDefinitionOverriding=null
		beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);

	if (this.allowCircularReferences != null) // eg2:allowCircularReferences=null
		beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}

4:加载BeanDefinition

@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
	XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
	beanDefinitionReader.setEnvironment(this.getEnvironment());
	beanDefinitionReader.setResourceLoader(this);
	beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

	// 对beanDefinitionReader设置setValidating
	initBeanDefinitionReader(beanDefinitionReader);

	// 加载xml配置信息
	loadBeanDefinitions(beanDefinitionReader);
}

    // 对beanDefinitionReader设置setValidating

protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
	// eg1:validating=true
	reader.setValidating(this.validating);
}

    // 加载xml配置信息

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
	// eg1:ClassPathXmlApplicationContext#getConfigResources()
	Resource[] configResources = getConfigResources();
	if (configResources != null) // eg1: configResources=null
		reader.loadBeanDefinitions(configResources);

	String[] configLocations = getConfigLocations();
	if (configLocations != null) // eg1: configLocations=["bean.xml"]
		reader.loadBeanDefinitions(configLocations);
}
// eg1: locations=["bean.xml"]
@Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
	Assert.notNull(locations, "Location array must not be null");
	int count = 0;
	for (String location : locations)
		count += loadBeanDefinitions(location);
	return count;
}
@Override
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
	return loadBeanDefinitions(location, null);
}

/**
 * 从指定的资源位置(resource location)加载bean定义。
 * 位置(location)也可以是位置模式(location pattern),前提是这个bean definition reader的ResourceLoader是一个ResourcePatternResolver。
 */
// eg1:location="bean.xml" actualResources=null
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
	ResourceLoader resourceLoader = getResourceLoader();
	// eg1:resourceLoader=ClassPathXmlApplicationContext@2bec854f
	if (resourceLoader == null)
		throw new BeanDefinitionStoreException("Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");

	if (resourceLoader instanceof ResourcePatternResolver) {
		try {
			// eg1:location="bean.xml",AbstractApplicationContext#getResources(location)
			Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);

			// eg1:resources=[ClassPathContextResource]
			int count = loadBeanDefinitions(resources);

			if (actualResources != null) // eg1:actualResources=null
				Collections.addAll(actualResources, resources);
			return count;
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException("Could not resolve bean definition resource pattern [" + location + "]", ex);
		}
	}
	else {
		Resource resource = resourceLoader.getResource(location);
		int count = loadBeanDefinitions(resource);
		if (actualResources != null) actualResources.add(resource);
		return count;
	}
}
// eg1:resources=[ClassPathContextResource]
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
	Assert.notNull(resources, "Resource array must not be null");
	int count = 0;
	for (Resource resource : resources) {
		// 加载配置
		count += loadBeanDefinitions(resource); // eg1: XmlBeanDefinitionReader#loadBeanDefinitions(resource)
	}
	return count;
}
/**
 * 从指定的XML文件中加载bean定义。
 */
// eg1:resource=ClassPathContextResource
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
	return loadBeanDefinitions(new EncodedResource(resource));
}

代码走到这一步,就跟xmlBeanFactory方法重合了。

obtainFreshBeanFactory() 的 2:获得BeanFactory

@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
	DefaultListableBeanFactory beanFactory = this.beanFactory;
	if (beanFactory == null) // eg1:beanFactory=DefaultListableBeanFactory@6e01f9b0
		throw new IllegalStateException("BeanFactory not initialized or already closed - " +
				"call 'refresh' before accessing beans via the ApplicationContext");
	return beanFactory;
}

/** 3:prepareBeanFactory 准备用于此上下文的beanFactory */

/**
 * 配置工厂的标准上下文特征,例如上下文的类加载器(context's ClassLoader)和后处理器(post-processors)
 */
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	/** 1: 设置beanFactory的classLoader */
	beanFactory.setBeanClassLoader(getClassLoader()); // eg1:DefaultResourceLoader#getClassLoader()

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

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

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

	/** 5: 设置7个需要忽略自动装配的接口,维护到ignoredDependencyInterfaces中 */
	beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
	beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
	beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
	beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
	beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
	beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
	beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);

	/** 6: 注册4个依赖,向resolvableDependencies中注册类及实现类*/
	beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
	beanFactory.registerResolvableDependency(ResourceLoader.class, this);
	beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
	beanFactory.registerResolvableDependency(ApplicationContext.class, this);

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

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

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

prepareBeanFactory方法的主要作用是配置工厂的标准上下文特征,如上下文的类加载 器和后处理器。操作步骤如下所述:

① 设置beanFactory的classLoader

/**
 * 返回用来加载类路径资源的类加载器(ClassLoader)。
 * 将被传递给这个资源加载器创建的所有ClassPathResource对象的ClassPathResource构造函数。
 */
@Override
@Nullable
public ClassLoader getClassLoader() {
	// eg1:classLoader=null
	return (this.classLoader != null ? this.classLoader : ClassUtils.getDefaultClassLoader());
}
/**
 * 返回要使用的默认类加载器:通常是线程上下文的类加载器(如果有的话);加载ClassUtils类的类加载器将用作备用。
 * 如果你想使用线程上下文的类加载器,而你显然更喜欢非空的类加载器引用,那么可以调用这个方法:例如,用于类路径资源加载(但不一定用于类。
 * forName也接受一个null类加载器引用)。
 */
@Nullable
public static ClassLoader getDefaultClassLoader() {
	ClassLoader cl = null;
	try {
		cl = Thread.currentThread().getContextClassLoader(); // 1:获得当前线程上下文的ClassLoader
	} catch (Throwable ex) {}

	if (cl == null) {
		cl = ClassUtils.class.getClassLoader(); // 2:获得ClassUtils类的ClassLoader
		if (cl == null) {
			try {
				cl = ClassLoader.getSystemClassLoader(); // 3:获得系统的类加载器
			} catch (Throwable ex) {}
		}
	}
	return cl;
}

(上面代码块:SPI破话双亲委派机制)

② 是否支持SpEL表达式解析,即:可以使用#{bean.xxx}的形式来调用相关属性值

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

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

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

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

(视频6-5:1h50min)

③ 添加1个属性编辑器ResourceEditorRegistrar,对bean的属性等设置管理的工具

什么是属性编辑器呢?在Spring加载bean的时候,可以把基本类型属性注入进来,但是 对于类似Date这种复杂属性就无法被识别了,不过可以通过属性编辑器解决。

因为date 属性是Date类型的,但是给配置的属性值是字符串类型的,所以需要进行一下转换。

以上例子:

@Data
public class Schedule {
    private String name;
    private Date date; // 添加Date类型的属性
}
public class DatePropertyEditor implements PropertyEditorRegistrar {
    @Override
    public void registerCustomEditors(PropertyEditorRegistry registry) {
        registry.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
    }
}
<!-- 属性编辑器演示 -->
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
	<property name="propertyEditorRegistrars">
		<list>
			<bean class="com.muse.springdemo.propertyeditor.DatePropertyEditor"/>
		</list>
	</property>
</bean>
<bean id="schedule" class="com.muse.springdemo.propertyeditor.Schedule">
	<property name="name" value="work"/>
	<property name="date" value="2023-01-01"/> <!-- date是Date类型,需要将String转换为Date -->
</bean>
@Test
void testPropertyEditor() {
	Schedule schedule = applicationContext.getBean("schedule", Schedule.class);
	log.info("schedule={}", schedule);
}

运行结果:

属性编辑器源码解析:

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

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

④ 添加1个bean的后置处理器ApplicationContextAwareProcessor

那既然ApplicationContextAwareProcessor是后置处理器,那它必然就已经实现了 BeanPostProcessor接口。那么问题来了,后置处理器会在什么时候被Spring调用呢?

⑤ 设置7个需要忽略自动装配的接口,维护到ignoredDependencyInterfaces中

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

⑥ 注册4个依赖,向resolvableDependencies中注册类及实现类

⑦ 添加1个bean的后置处理器ApplicationListenerDetector

⑧ 增加对AspectJ的支持

⑨ 注册4个默认的系统环境bean

/** 4:激活各种BeanFactoryPostProcessor的后置处理器 */
            invokeBeanFactoryPostProcessors(beanFactory);

这段方法是用来处理 BeanFactoryPostProcessor的。

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

4-1 PropertySourcesPlaceholderConfigurer 的应用(源码在本节最下面)

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

然后创建message的Bean配置信息,变量引用:${message.msg}。创建 PropertySourcesPlaceholderConfigurer的Bean配置信息。通过locations属性,来指定配 置文件所在路径。

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

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

类的继承关系图请见下图所示:

@Data
public class Message {
    private String msg;
}

 common.properties 文件:

message.msg=Hello World!
<!-- PropertySourcesPlaceholderConfigurer演示 -->
<bean id="message" class="com.muse.springdemo.placeholder.Message">
	<property name="msg">
		<value>${message.msg}</value>
	</property>
</bean>
<bean id="messageHandler" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
	<property name="locations">
		<list>
			<value>prop/common.properties</value>
		</list>
	</property>
</bean>
@Test
void testPropertySourcesPlaceholderConfigurer() {
	Message message = applicationContext.getBean("message", Message.class);
	log.info("message={}", message);
}

运行结果:

4-2 自定义 BeanFactoryPostProcessor 的应用(源码在本节最下面)

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

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

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

@Data
public class AllMessage {
    private String msg1;
    private String msg2;
    private String msg3;
    private String msg4;
}
@Data
public class MuseBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

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

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        for (String beanName : beanFactory.getBeanDefinitionNames()) {
            BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
            StringValueResolver svr = strVal -> dirtyWords.contains(strVal.toLowerCase()) ? "******" : strVal;
            BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(svr);
            visitor.visitBeanDefinition(beanDefinition);
        }
    }
}
<!-- BeanFactoryPostProcessor演示 -->
<bean id="allMessage" class="com.muse.springdemo.beanfactorypostprocessor.AllMessage">
	<property name="msg1" value="大笨蛋"/>
	<property name="msg2" value="双击666"/>
	<property name="msg3" value="傻子"/>
	<property name="msg4" value="滚吧"/>
</bean>

<bean id="museBFPP" class="com.muse.springdemo.beanfactorypostprocessor.MuseBeanFactoryPostProcessor">
	<property name="dirtyWords">
		<set>
			<value>大笨蛋</value>
			<value>好蠢啊</value>
			<value>丑哭了</value>
			<value>傻子</value>
			<value>滚吧</value>
			<value>这人真垃圾</value>
		</set>
	</property>
</bean>
@Test
void testBeanFactoryPostProcessor() {
	AllMessage allMessage = applicationContext.getBean("allMessage", AllMessage.class);
	log.info("allMessage={}", allMessage);
}

运行结果:

4-3 invokeBeanFactoryPostProcessors 源码解析(30min-1h1min)

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory,
												   List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
	Set<String> processedBeans = new HashSet<>(); // 用于存储已经处理过的【处理器名称】

	/** 1:对BeanDefinitionRegistry类型进行处理,包括【硬编码】+【配置方式】*/
	if (beanFactory instanceof BeanDefinitionRegistry) { // eg1: beanFactory=DefaultListableBeanFactory@6b58b9e9
		BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
		// 通过【硬编码】注册的BeanFactoryPostProcessor
		List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
		// 通过【硬编码】注册的BeanDefinitionRegistryPostProcessor
		List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

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

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

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

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

		/**
		 * 1.5:处理BeanDefinitionRegistryPostProcessor实例集合和BeanFactoryPostProcessor实例集合,调用其
		 * postProcessBeanFactory(beanFactory)方法
		 */
		invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
	}

	/** 2:对非BeanDefinitionRegistry类型进行处理【硬编码】+【配置方式】 ,调用其postProcessBeanFactory(beanFactory)方法 */
	else invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);

	/** 3:处理所有通过【配置方式】注册且实现了BeanFactoryPostProcessor实例集合,调用其postProcessBeanFactory方法 */
	String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
	List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
	List<String> orderedPostProcessorNames = new ArrayList<>();
	List<String> nonOrderedPostProcessorNames = new ArrayList<>();
	for (String ppName : postProcessorNames) {
		if (processedBeans.contains(ppName)) {
			// skip - already processed in first phase above
		}
		else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class))
			priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); // 如果实现了PriorityOrdered接口,则进行排序
		else if (beanFactory.isTypeMatch(ppName, Ordered.class)) // 如果实现了Ordered接口,则进行排序
			orderedPostProcessorNames.add(ppName);
		else nonOrderedPostProcessorNames.add(ppName); // 否则,不排序了
	}

	/** 3-1:对实现了“PriorityOrdered接口”的进行处理【配置方式】 ,调用其postProcessBeanFactory(beanFactory)方法 */
	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
	invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

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

	/** 3-3:对没有实现(“PriorityOrdered接口”或“Ordered接口”)进行处理【配置方式】 ,调用其postProcessBeanFactory(beanFactory)方法 */
	List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
	for (String postProcessorName : nonOrderedPostProcessorNames)
		nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
	invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

	beanFactory.clearMetadataCache();
}

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

① 一个类实现了ConfigurableListableBeanFactory接口+BeanDefinitionRegistry接口

② 一个类仅实现了ConfigurableListableBeanFactory接口

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

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

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

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

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

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

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

 /** 5:注册各种Bean的后置处理器,在getBean时才会被调用 */
            registerBeanPostProcessors(beanFactory);
            beanPostProcess.end();

/**
 * 注册BeanPostProcessor
 */
public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
	// eg1:postProcessorNames=["com.muse.springdemo.beanpostprocessor.MuseBeanPostProcessor#0"]
	String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

	/** 1:BeanPostProcessorChecker是一个用于检查操作的后置处理器,即:当Spring配置中的后处理器还没有被注册就已经开始了bean的初始化时,那么Checker就会打印提示信息日志 */
	int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; // eg1:beanProcessorTargetCount=4
	beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

	/** 2:根据不同接口,进行"分组"操作 */
	List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); // 实现了PriorityOrdered接口
	List<BeanPostProcessor> internalPostProcessors = new ArrayList<>(); // 实现了MergedBeanDefinitionPostProcessor接口
	List<String> orderedPostProcessorNames = new ArrayList<>(); // 实现了Ordered接口
	List<String> nonOrderedPostProcessorNames = new ArrayList<>(); // 未实现排序接口
	for (String ppName : postProcessorNames) {
		/** 存储实现了PriorityOrdered接口的后置处理器 */
		if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			priorityOrderedPostProcessors.add(pp);
			/** 存储实现了PriorityOrdered接口并且是MergedBeanDefinitionPostProcessor类型后置处理器 */
			if (pp instanceof MergedBeanDefinitionPostProcessor) internalPostProcessors.add(pp);
		}
		/** 存储实现了Ordered接口的后置处理器 */
		else if (beanFactory.isTypeMatch(ppName, Ordered.class)) orderedPostProcessorNames.add(ppName);
		/** 存储未实现排序接口的后置处理器 */
		else nonOrderedPostProcessorNames.add(ppName); // eg1:ppName="com.muse.springdemo.beanpostprocessor.MuseBeanPostProcessor#0"
	}

	/** 3:注册实现PriorityOrdered的BeanPostProcessors */
	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
	registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

	/** 4:注册实现Ordered的BeanPostProcessors。 */
	List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
	for (String ppName : orderedPostProcessorNames) { // eg1:orderedPostProcessorNames.size()=0
		BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
		orderedPostProcessors.add(pp);
		if (pp instanceof MergedBeanDefinitionPostProcessor) {
			internalPostProcessors.add(pp); // 存储实现了Ordered接口并且是MergedBeanDefinitionPostProcessor类型后置处理器
		}
	}
	sortPostProcessors(orderedPostProcessors, beanFactory);
	registerBeanPostProcessors(beanFactory, orderedPostProcessors);

	/** 5:现在,注册没有实现排序接口的BeanPostProcessors */
	List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
	// eg1:nonOrderedPostProcessorNames=["com.muse.springdemo.beanpostprocessor.MuseBeanPostProcessor#0"]
	for (String ppName : nonOrderedPostProcessorNames) {
		BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
		nonOrderedPostProcessors.add(pp); // eg1:pp=MuseBeanPostProcessor@3088
		if (pp instanceof MergedBeanDefinitionPostProcessor) { // eg1:false
			internalPostProcessors.add(pp); /** 存储没有实现排序接口并且是MergedBeanDefinitionPostProcessor类型后置处理器 */
		}
	}
	registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

	/** 6:注册MergedBeanDefinitionPostProcessor类型后置处理器 */
	sortPostProcessors(internalPostProcessors, beanFactory);
	registerBeanPostProcessors(beanFactory, internalPostProcessors);

	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

举例:

public class MuseBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("allMessage")) {
            System.out.println("------------------allMessage------------------");
        }
        return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }
}
<!-- BeanPostProcessor演示 -->
<bean class="com.muse.springdemo.beanpostprocessor.MuseBeanPostProcessor"/>
@Test
void testBeanPostProcessor() {
	/** test1:注释掉beanFactory,然后再执行 */
	log.info("From ApplicationContext");
	Gun m416 = applicationContext.getBean("m416", Gun.class);
	log.info("gun={}", m416);

	/** test2:注释掉applicationContext,然后再执行 */
//         log.info("From BeanFactory");
//         Gun m416 = beanFactory.getBean("m416", Gun.class);
//         log.info("gun={}", m416);
}

test1的运行结果:

test2 的运行结果:

看了registerBeanPostProcessors方法的源码后,可以发现,其实与上一部分介绍的invokeBeanFactoryPostProcessors方法逻辑很像,具体逻辑如下所示:

① 针对实现了PriorityOrdered接口的BeanPostProcessor后置处理器执行排序和注册操 作。

② 针对实现了Ordered接口的BeanPostProcessor后置处理器执行排序和注册操作。

③ 针对没有实现排序接口的BeanPostProcessor后置处理器执行注册操作。

④ 针对MergedBeanDefinitionPostProcessor类型的后置处理器执行注册操作。

/** 6:为上下文初始化消息源(即:国际化处理)*/
            initMessageSource();

Spring国际化是根据客户端的系统语言类型返回对应的界面,这个便是所谓的i18n国际化 (internationalization)。国际化信息也称之为本地化信息,需要两个条件来最终决定:

① 语言类型(eg:中文)

② 国家/地区的类型(ge:中国大陆、中国台湾、中国香港、新加坡、马来西亚……)

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

① 指定语言和国家/地区——new Locale("zh", "CN") 或 Locale.CHINA

② 指定语言——new Locale("zh") 或 Locale.CHINESE

③ 根据操作系统默认语言设置——Locale.getDefault()

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

① ResourceBundleMessageSource:允许通过资源名加载国际化资源。

② ReloadableResourceBundleMessageSource:与ResourceBundleMessageSource功 能相似,额外提供定时刷新功能,不用重启系统,即可更新资源信息。

③ StaticMessageSource:主要用于程序测试,允许通过编程的方式提供国际化信息。

④ DelegatingMessageSource:为方便操作MessageSource的代理类

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

/**
 * 初始化MessageSource。如果在此上下文中没有定义,则使用父元素。
 */
protected void initMessageSource() {
	// eg1: AbstractRefreshableApplicationContext#getBeanFactory()
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();

	/** 1: 如果需要用户自定义国际化资源,则需要创建一个bean的id必须是“messageSource”(硬编码)的bean */
	if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) { // eg1:true  MESSAGE_SOURCE_BEAN_NAME 为 messageSource,也就是bean id
		this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
		if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) { // eg1:parent=null
			HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
			if (hms.getParentMessageSource() == null)
				hms.setParentMessageSource(getInternalParentMessageSource());
		}
	}
	/** 2: 如果不存在名称为"messageSource"的bean,则创建并注册到Spring中 */
	else {
		DelegatingMessageSource dms = new DelegatingMessageSource();
		dms.setParentMessageSource(getInternalParentMessageSource());
		this.messageSource = dms; // 赋值给全局变量messageSource
		beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource); // 注册messageSource名称的Bean
	}
}

举例:

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

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

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

源代码:

hello=Hello World!
hello=\u4f60\u597d \u4e16\u754c\uff01
<!-- 国际化演示 -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
	<property name="basenames">
		<list>
			<value>META-INF/i18n</value> <!-- 表示在META-INF目录下,以i18n开头 -->
		</list>
	</property>
</bean>
@Test
void testI18n() {
	System.out.println("Locale.US=" + applicationContext.getMessage("hello", null, Locale.US));
	System.out.println("Locale.CHINA=" + applicationContext.getMessage("hello", null, Locale.CHINA));
}

运行结果:

/** 7:为上下文初始化应用事件广播器 */
            initApplicationEventMulticaster();
            onRefresh(); // 初始化特定上下文子类中的其他特殊bean(空方法,可由子类实现)

initApplicationEventMulticaster()方法的具体处理逻辑:

① 如果用户自定义了EventMulticaster,则从Spring中获取用户自定义的事件广播器。

② 如果用户没有自定义EventMulticaster,则向Spring中注册默认的 SimpleApplicationEventMulticaster广播器。

/**
 * 初始化ApplicationEventMulticaster。如果上下文中没有定义,则使用SimpleApplicationEventMulticaster。
 */
protected void initApplicationEventMulticaster() {
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	/** 1: 如果用户【自定义】了名称为"applicationEventMulticaster"的EventMulticaster,则从Spring中获取用户自定义的事件广播器 */
	if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME))   // APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
		this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME,
				ApplicationEventMulticaster.class);

	/** 2: 如果用户【没有自定义】EventMulticaster,则向Spring中注册名称为"applicationEventMulticaster"的广播器 */
	else {
		this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
		beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
	}
}

7-1  SimpleApplicationEventMulticaster是如何处理广播事件的

举例:

/**
 * 自定义应用事件类
 */
public class MuseApplicationEvent extends ApplicationEvent {

    private String msg;

    public MuseApplicationEvent(String source) {
        super(source);
        this.msg = source;
    }

    public void print() {
        System.out.println("MuseApplicationEvent=" + msg);
    }
}
/**
 * 自定义应用监听类
 */
public class MuseApplicationListener implements ApplicationListener {
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof MuseApplicationEvent) {
            MuseApplicationEvent museApplicationEvent = (MuseApplicationEvent) event;
            museApplicationEvent.print();
        }
    }
}
<!-- ApplicationEvent演示 -->
<bean id="museListener" class="com.muse.springdemo.applicationevent.MuseApplicationListener"/>
@Test
void testApplicationEvent() {
	applicationContext.publishEvent(new MuseApplicationEvent("Hello World!"));
}

运行结果:

/** 8:在所有注册的bean中查找listener bean,并注册到消息广播器中 */
            registerListeners();

注册监听器:

注册监听器的方法也比较简单清晰,它一共做到了如下3个步骤:

① 添加以硬编码方式注册的监听器

② 添加以配置文件方式注册的监听器

③ 发送在多播设置之前发布的ApplicationEvent事件

/**
 * 添加实现ApplicationListener作为监听器的bean。不会影响其他监听器,这些监听器可以不作为bean添加。
 */
protected void registerListeners() {
	/** 1: 添加以【硬编码】方式注册的监听器 */
	for (ApplicationListener<?> listener : getApplicationListeners()) // eg1:getApplicationListeners().size()=0
		getApplicationEventMulticaster().addApplicationListener(listener);

	/** 2: 添加以【配置文件】方式注册的监听器 */
	String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
	for (String listenerBeanName : listenerBeanNames) // eg1:listenerBeanNames=[museListener]
		getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);

	/** 3: 发送在多播设置之前发布的ApplicationEvent事件 */
	Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
	this.earlyApplicationEvents = null;
	if (!CollectionUtils.isEmpty(earlyEventsToProcess)) // eg1: earlyEventsToProcess.size()=0
		for (ApplicationEvent earlyEvent : earlyEventsToProcess)
			getApplicationEventMulticaster().multicastEvent(earlyEvent);
}

 /** 9:初始化剩下的单例(非惰性non-lazy-init)*/
            finishBeanFactoryInitialization(beanFactory);

初始化非延迟加载单例:

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

① 为上下文添加ConversionService

② 为上下文添加EmbeddedValueResolver(嵌入值解析器)

③ 初始化LoadTimeWeaverware类型的Bean

④ 停止使用临时ClassLoader进行类型匹配

⑤ 冻结配置

⑥ 实例化所有剩余的(非惰性初始化:lazy-init=false)单例。

@Test
void testLazyInit() {
log.info("创建applicationContext完毕!");
applicationContext.getBean("lazyInitBean", LazyInitBean.class);
log.info("getBean方法被调用完毕");

//        log.info("创建beanFactory完毕!");
//        beanFactory.getBean("lazyInitBean", LazyInitBean.class);
//        log.info("getBean方法被调用完毕");
}	/**
 * 完成这个上下文的bean工厂的初始化,初始化所有剩余的单例bean。
 */
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
	/** 1:为beanFactory添加ConversionService实例对象 */
	if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && // eg1: false
			beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class))
		beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));

	/** 2:为beanFactory添加EmbeddedValueResolver(嵌入值解析器)*/
	if (!beanFactory.hasEmbeddedValueResolver()) // eg1: false
		beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));

	/** 3:初始化LoadTimeWeaverware类型的Bean */
	String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
	for (String weaverAwareName : weaverAwareNames) // eg1:weaverAwareNames=[]
		getBean(weaverAwareName);

	/** 4:停止使用临时ClassLoader进行类型匹配 */
	beanFactory.setTempClassLoader(null);

	/** 5:冻结配置 */
	beanFactory.freezeConfiguration();

	/** 6:实例化所有剩余的(非惰性初始化:lazy-init=false)单例 */
	beanFactory.preInstantiateSingletons();
}
public void preInstantiateSingletons() throws BeansException {
	// eg1:
	// beanDefinitionNames=[
	// "m416","m416OfMeta","writer","pencil","brush","coder","fakerCoder","replacer","bmwCar","cat", "ent", "customUser",
	// "computer","helloAware","hello","schedule","org.springframework.beans.factory.config.CustomEditorConfigurer#0",
	// "message","messageHandler","allMessage","museBFPP","com.muse.springdemo.beanpostprocessor.MuseBeanPostProcessor#0",
	// "messageSource","museListener","org.springframework.web.servlet.view.InternalResourceViewResolver#0"
	// ]
	List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

	/** 1:触发所有非惰性单例bean的初始化 */
	for (String beanName : beanNames) {
		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); // eg1:beanName="m416"
		if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { // eg1:true
			if (isFactoryBean(beanName)) { // eg1:false
				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(
								/** 调用SmartFactoryBean#isEagerInit()方法 */
								(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
								getAccessControlContext());
					else
						/** 调用SmartFactoryBean#isEagerInit()方法 */
						isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit());

					if (isEagerInit) getBean(beanName);
				}
			}
			else getBean(beanName); // eg1:beanName="m416"
		}
	}
	/** 2:触发所有适用bean的后初始化回调,调用所有SmartInitializingSingleton#afterSingletonsInstantiated方法 */
	for (String beanName : beanNames) {
		Object singletonInstance = getSingleton(beanName); // eg1:beanName="m416"
		if (singletonInstance instanceof SmartInitializingSingleton) { // eg1:false
			StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize").tag("beanName", beanName);
			SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
			if (System.getSecurityManager() != null)
				AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
					/** 调用SmartInitializingSingleton#afterSingletonsInstantiated()方法 */
					smartSingleton.afterSingletonsInstantiated();
					return null;
				}, getAccessControlContext());
			else
				/** 调用SmartInitializingSingleton#afterSingletonsInstantiated()方法 */
				smartSingleton.afterSingletonsInstantiated();
			smartInitialize.end();
		}
	}
}

 

初始化示例:

bean定义的时候通过lazy-init属性来配置bean是否是延迟加载

① true:延迟初始化

② false:实时初始化(不配置默认就是false)

首先,创建一个Bean,然后在构造函数中输出一行日志,用于后续测试时验证该对象是否被创建

@Slf4j
public class LazyInitBean {
    public LazyInitBean() {
        log.info("----------LazyInitBean的构造方法被调用----------");
    }
}

在bean.xml配置文件中,开启惰性初始化。

<!-- LazyInit演示,默认:lazy-init="false" -->
<bean id="lazyInitBean" class="com.muse.springdemo.lazyinit.LazyInitBean" lazy-init="true"/>
@Test
void testLazyInit() {
	log.info("创建applicationContext完毕!");
	applicationContext.getBean("lazyInitBean", LazyInitBean.class);
	log.info("getBean方法被调用完毕");

//        log.info("创建beanFactory完毕!");
//        beanFactory.getBean("lazyInitBean", LazyInitBean.class);
//        log.info("getBean方法被调用完毕");
}

运行结果:

从执行结果中可以看到,由于开启了惰性初始化,所以创建完ApplicationContext对象, 调用了getBean方法之后,才创建的LazyInitBean实例对象。而默认的bean是实时初始化的, 那么就会在创建ApplicationContext对象过程中被提前初始化,运行结果如上所示。

懒加载:先加载,获得bean会比较快,但是启动速度会有影响。反之。

test案例中,beanFactory 和 applicationContext 的区别:beanFactory不会提前创建bean,只有在调用get的时候才会创建bean。application会先创建bean。

/** 10:完成refresh,通知lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知 */
            finishRefresh();

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

① start():Spring启动的时候,调用该方法开始生命周期;

② stop():Spring关闭的时候,调用该方法结束生命周期;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值