上一篇:8-Spring源码解析之refresh(2)——【prepareRefresh】与【ConfigurableListableBeanFactory】
上一篇文章介绍了refresh
方法中的前两个方法,本篇文章我们继续介绍refresh
方法中的第三个方法prepareBeanFactory
和第四个方法postProcessBeanFactory
。
一、 prepareBeanFactory
这个方法设置beanFactory
的标准上下文特征,为beanFactory
设置类加载器、后置处理器等。其中主要注意一下这里面增加了2个beanFactory
的后置处理器,由于Bean
和beanFactory
在Spring中都有后置处理器,所以要优先注意一下。这里需要强调一点:beanFactory
在想要拥有后置处理器时,必须通过显示的调用addBeanPostProcessor
才能获得。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 设置beanFactory的类加载器classLoader为当前context的类加载器.
beanFactory.setBeanClassLoader(getClassLoader());
// 设置SpEL表达式解析器(在Bean初始化完成之后填充属性的时候用到)
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
// 添加属性编辑注册器(注册属性编辑器),属性编辑器实际上是属性的类型转换器
// 因为bean的属性配置都是字符串类型的 实例化的时候要将这些属性转换为实际类型
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 添加beanFactory的后置处理器
// 在Bean初始化之前,调用ApplicationContextAwareProcessor的postProcessBeforeInitialization
// 处理所有的Aware接口,进行如下操作:
// 1. 如果bean实现了EnvironmentAware接口,调用bean.setEnvironment
// 2. 如果bean实现了EmbeddedValueResolverAware接口,调用bean.setEmbeddedValueResolver
// 3. 如果bean实现了ResourceLoaderAware接口,调用bean.setResourceLoader
// 4. 如果bean实现了ApplicationEventPublisherAware接口,调用bean.setApplicationEventPublisher
// 5. 如果bean实现了MessageSourceAware接口,调用bean.setMessageSource
// 6. 如果bean实现了ApplicationContextAware接口,调用bean.setApplicationContext
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 忽略自动装配,在注入的时候忽略此方法指定的接口类。也就是指定的接口不会被注入进去
// 可以忽略的原因是:ApplicationContextAwareProcessor把这五个接口的实现工作做完了
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
// 下面这4个class 会被加入到beanFactory的resolvableDependencies字段里面缓存这,
// 为后面处理依赖注入的时候使用 DefaultListableBeanFactory#resolveDependency处理依赖关系
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的后置处理器 事件监听器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
1.1 增加SpEL
语言支持
SpEL 表达式语言全称为“Spring Expression Language”. SpEL 是单独模块,只依赖于core模块,不依赖于其他模块,可以单独使用。
SpEL 使用 #{},作为定界符,所有在大括号中的字符都将被认为是 SpEL。
例子:
<bean id="rdsDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="${spring.datasource.druid.url}"/>
</bean>
在prepareBeanFactory
方法中主要通过beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
注册语言解析器,就可以对SpEL进行解析了。
解析的动作是在 bean进行初始化的时候会有属性填充的一步,而在这一步中Spring会调用 AbstractAutowireCapableBeanFactory
类的 applyPropertyValues
函数来完成功能。
1.2 添加 ApplicationContextAwareProcessor
处理器
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
方法。
我们先看一下类ApplicationContextAwareProcessor
的结构。
该类是BeanPostProcessor
的实现类。我们知道BeanPostProcessor
类,在bean的init方法执行前后会调用postProcessBeforeInitialization
和postProcessAfterInitialization
方法。
因此Spring增加了这个类,就是为了在bean的init方法执行时分别调用postProcessBeforeInitialization
和postProcessAfterInitialization
方法。那么我们就来具体看看这两个方法的实现情况。
1.2.1 postProcessBeforeInitialization
方法
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
if (System.getSecurityManager() != null &&
(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
// 调用这个方法主要是为了调用该类中的 invokeAwareInterfaces 方法
invokeAwareInterfaces(bean);
return null;
}
}, acc);
}
else {
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);
}
}
}
我们从上面的invokeAwareInterfaces
方法中可以看出,实现了对应类型的Bean,在初始化之前会根据bean实现的类来获取对应的资源。
执行完上面语句后,beanFactory
中便有了 ApplicationContextAwareProcessor
后置处理器。我们从下面的图片可以看出,此时 beanFactory
中 仅有一个后置处理器。
1.2.2 postProcessAfterInitialization
方法
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
1.3 设置忽略依赖
在1.2.1 节我们知道,当Spring将 ApplicationContextAwareProcessor
注册之后,在invokeAwareInterfaces
方法中调用的 Aware 类已经不是普通的 bean了。如类已经实现了 接口 ApplicationContextAware
时,该类就有applicationContext
属性。 因此当然需要在Spring做bean的依赖注入的时候忽略它们。 而 ignoreDependencyInterface
功能便是如此。
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
1.4 注册依赖
当注册依赖之后,比如当注册了对 BeanFactory
的解析依赖之后,当 bean 的属性注入的时候,一旦检测到属性为 BeanFactory
类型便会将 BeanFactory
的实例注入进去。
1.5 事件监听后置处理器ApplicationListenerDetector
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
二、 postProcessBeanFactory
方法
该方法是一个留给子类的空方法。子类通过重写这个方法来在BeanFactory创建并预准备完成以后做进一步的设置
三、 总结
以上是refresh
方法中调用的第三个方法prepareBeanFactory
和第四个方法postProcessBeanFactory
,
一下篇文章我们来接着介绍refresh
的第五个方法,也是非常重要的方法:invokeBeanFactoryPostProcessors(beanFactory);