AbstractApplicationContext类refresh()方法中的第三个调用方法prepareBeanFactory()的跟踪。
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
...
// Prepare the bean factory for use in this context.
// 准备在上下文中bean factory的使用
prepareBeanFactory(beanFactory);
···
}
- 为工厂设置类的加载器、表达式解析器、属性编辑器注册器等
- 为工厂添加后处理器、要忽略的依赖接口
- 在工厂中注册可解析的依赖
- 在工厂中提前注册一些单例Bean ```java /**
- Configure the factory’s standard context characteristics,
- such as the context’s ClassLoader and post-processors. *
配置工厂的标准上下文特征,比如上下文的ClassLoader和post-processors */ protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { //告知内部的bean工厂,使用上下文的类加载器 beanFactory.setBeanClassLoader(getClassLoader());
//设置bean表达式解析器, //StandardBeanExpressionResolver内部expressionParser属性默认SpelExpressionParser类型 //spel = spring el表达式 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//将ResourceEditorRegistrar实例添加到工厂的propertyEditorRegistrars属性中, //propertyEditorRegistrars是一个LinkedHashSet,里面的元素将会应用到工厂bean中 //ResourceEditorRegistrar持有上下文和environment的引用 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 使用上下文回调配置bean 工厂 //在工厂的beanPostProcessor属性中添加处理器,beanPostProcessor是一个ArrayList beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
//在工厂的ignoredDependencyInterfaces属性中添加Aware系列接口, //ignoredDependencyInterfaces是一个HashSet beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory. // MessageSource registered (and found for autowiring) as a bean.
// 在普通的工厂中,BeanFactory接口并没有按照resolvable类型进行注册 // MessageSource被注册成一个Bean(并被自动注入)
//BeanFactory.class为key,beanFactory为value放入到了beanFactory的resolvableDependencies属性中 //resolvableDependencies是一个ConcurrentHashMap,映射依赖类型和对应的被注入的value //这样的话BeanFactory/ApplicationContext虽然没有以bean的方式被定义在工厂中, //但是也能够支持自动注入,因为他处于resolvableDependencies属性中 beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
//再将上下文的一些接口与上下文本身做映射,一一放入到resolvableDependencies中 beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Detect a LoadTimeWeaver and prepare for weaving, if found. // 检测LoadTimeWeaver,如果有就准备织入 //1.跟踪进入,浅看下containsBean方法 if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
//如果有LoadTimeWeaver,加入bean后处理器
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
// 为匹配类型设置一个临时的ClassLoader
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans. // 注册默认的environment beans
// 判断目前这个bean工厂中是否包含指定name的bean,忽略父工厂 if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
//虽然XmlWebApplicationContext中持有默认实现的StandardServletEnvironment
//但是没有注册到beanFactory中,通过getEnvironment方法拿到持有的引用
//2.注册environment单例
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
} if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
//注册systemProperties单例
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
} if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
//注册systemEnvironment单例
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
} }
<a name="IVQEs"></a>
## 一、 增加SPEL语言的支持
Spring 表达式语言全称为 “Spring Expression Language”,缩写为 “SpEL”,类似于Struts 2x 中使用的OGNL表达式语言,能在运行时构建复杂表达式、存取对象图属性、对象方法调用等, 并且能与Spring功能完美整合,比如能用 来配置bean定义。SpEL是单独模块,只依赖于core 模块,不依赖于其他模块,可以单独使用。<br />SpEL使用#{...}为定界符,所有在花括号中的字符都将被认为是SpEL,使用格式如下:
```xml
<bean id = "saxophone" value = "com.xxx.xxx.Xxx"/>
<bean >
<property name="instrument" value="#{saxophone}"/>
<bean/>
相当于:
<bean id = "saxophone" value = "com.xxx.xxx.Xxx"/>
<bean >
<property name="instrument" ref="saxophone"/>
<bean/>
当然,上面只是列举了其中最简单的使用方式,SPEL功能非常强大,使用好可以大大提高开发效率,这里只为唤起读者的记忆来帮助我们理解源码,有兴趣的读者可以进一步深入研究。
在源码中通过代码beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver())
注册语言解析器,就可以对SPEL进行解析了,那么在注册解析器后 Spring 又是在什么时候调用这个解析器进行解析呢?
之前我们讲解过 Spring 在 bean 进行初始化的时候会有属性填充的一步,而在这一步中 Spring 会调用AbstractAutowireCapableBeanFactory
类的 applyPropertyValues
函数来完成功能。就在这个函数中,会通过构造 BeanDefinitionValueResolver
类型实例 valueResolver
来进行属性值的解析。同时,也是在这个步骤中一般通过 AbstractBeanFactory
中的evaluateBeanDefinitionString
方法去完成 SPEL 的解析。
二、增加属性注册编辑器
JavaBean API 中提供了这样一个接口:java.beans.PropertyEditor
,该接口提供了将字符串值(String类型)映射为非String类型的方法。它便是传说中的属性编辑器。通过实现该接口,用户可以编写自定义属性编辑器,以将spring配置文件中的字符串转换成相应的对象注入。
但该接口有12个方法,如果用户要实现该接口编写自定义的属性编辑器会比较麻烦。幸运的是有一个好用的这个接口的实现类:`java.beans.PropertyEditorSupport`,我们可以继承这个实现类,覆写其中的`setAsText(String value)`方法,来实现我们的自定义属性编辑器。[
](https://blog.51cto.com/xiannenglin/435814)
配置属性自定义转换器可以参考:
10-Spring-配置属性自定义转换
Spring提供了一个配置类CustomEditorConfigurer
,可以将自定义的属性编辑器注入到Spring
中。此类实现了BeanFactoryPostProcessor
接口,BeanFactoryPostProcessor
可以在Bean实例化之前,往Spring容器中注入其他Bean。
从上面的CustomEditorConfigurer继承关系图可以看出,CustomEditorConfigurer实现了BeanFactoryPostProcessor接口。BeanFactoryPostProcessor是BeanFactory的后置处理器(BeanFactoryPostProcessor能定制和修改BeanFactory的内容,如覆盖或添加属性)。在BeanFactory标准初始化之后调用,这时所有的bean定义已经保存加载到beanFactory,但是bean的实例还未创建(即在Spring源码中refresh方法中的**invokeBeanFactoryPostProcessors**_**(**_**beanFactory**_**)**_**;**
这个方法处理的是 实现BeanFactoryPostProcessor 接口的 Bean)。
理清楚BeanFactoryPostProcessor的功能作用后,下面进行分析CustomEditorConfigurer的工作原理。
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
if (this.propertyEditorRegistrars != null) {
for (PropertyEditorRegistrar propertyEditorRegistrar : this.propertyEditorRegistrars) {
beanFactory.addPropertyEditorRegistrar(propertyEditorRegistrar);
}
}
if (this.customEditors != null) {
this.customEditors.forEach(beanFactory::registerCustomEditor);
}
}
CustomEditorConfigurer,它是一个特殊的BeanFactoryPostProcessor,可以将自定义的PropertyEditor或者PropertyEditorRegistrar实现存入其内部的customEditors和propertyEditorRegistrars属性中,启动项目之后,它的postProcessBeanFactory方法会在所有普通bean实例化和初始化之前(创建BeanWrapper之前)调用beanFactory来将这些PropertyEditor和propertyEditorRegistrars注册到AbstractBeanFactory的customEditors和propertyEditorRegistrars缓存。
基于以上的配置,在Spring bean对应的BeanWrapper初始化时,会自动从AbstractBeanFactory的customEditors和propertyEditorRegistrars缓存中将自定义的PropertyEditor注册到自己内部(位于AbstractBeanFactory#initBeanWrapper方法中),之后被BeanWrapper用于创建和填充 Bean 实例的类型转换。
但是请注意,这种配置不适用于Spring MVC的数据绑定,因为DataBinder默认不会查找这里注册到AbstractBeanFactory中的customEditors和propertyEditorRegistrars缓存,数据绑定时需要的自定义Editor必须在org.springframework.validation.DataBinder中手动注册(通过Spring MVC的@InitBinder方法)。
三、 添加 ApplicationContextAwareProcessor 处理器
了解了属性编辑器的使用后,接下来我们继续通过AbstractApplicationContext
的 prepareBeanFactory
方法的主线来进行函数跟踪。对于 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this))
其实主要目的就是注册个 BeanPostProcessor
,而真正的逻辑还是在ApplicationContextAwareProcessor
中。ApplicationContextAwareProcessor
实现BeanPostProcessor
接口,我们回顾下之前讲过的内容,在bean实例化的时候,也就是Spring
激活bean的init-method
的前后,会调用BeanPostProcessor
的 postProcessBeforelnitialization
方法和postProcessAfterlnitialization
方法。问样,对于ApplicationContextAwareProcessor
我们也关心这两个方法。对于postProcessAfterlnitialization
方法,在ApplicationContextAwareProcessor
中并没有做过多逻辑处理。
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
那么,我们重点看一下postProcessBeforelnitialization 方法。
@Override
@Nullable
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
// 省略代码....
else {
// 在postProcessBeforeInitialization调用invokeAware接口
invokeAwareInterfaces(bean);
}
return bean;
}
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
四. 设置忽略依赖
当Spring 将ApplicationContextAwareProcessor
注册后,那么在invokeAwarelnterfaces
方法中间接调用的 Aware 类已经不是普通的 bean 了,如 ResourceLoaderAware、ApplicationEventPublisher Aware等,那么当然需要在Spring做bean的依赖注入的时候忽略它们。而ignoreDependencylnterfece的作用正是在此。prepareBeanFactory
方法中就有如下代码来禁止Environment
或者ApplicationContext
通过Autowired
等方式获取