目录
2.invokeBeanFactoryPostProcessors
容器完成配置文件的解析和Bean的加载、注册之后,ApplicationContext就已经拥有了BeanFactory的所有功能了,但是仅仅如此,还无法体现ApplicationContext与BeanFactory之间的差异。在refresh方法中,还有很多后续步骤,用于对容器功能进行扩展:
this.prepareBeanFactory(beanFactory); //对BeanFactory进行功能填充
this.postProcessBeanFactory(beanFactory); //允许子类在所有的bean尚未初始化之前注册BeanPostProcessor
this.invokeBeanFactoryPostProcessors(beanFactory); //是我们可以在bean初始化之前修改Bean的定义
this.registerBeanPostProcessors(beanFactory); //注册拦截Bean创建的后处理器
this.initMessageSource(); //初始化消息源,用于国际化
this.initApplicationEventMulticaster(); //初始化应用程序的事件广播器
this.onRefresh(); //空方法,作为扩展点
this.registerListeners(); //查找并注册Listener Bean
this.finishBeanFactoryInitialization(beanFactory); //初始化剩余的单例
this.finishRefresh(); //完成刷新,并通知相关监听器
这里先看下前四个方法。
1.prepareBeanFactory方法
该方法大致可以分成四块来看。
1.1 扩展容器的组件
beanFactory.setBeanClassLoader(this.getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
if (beanFactory.containsBean("loadTimeWeaver")) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
1)setBeanClassLoader不难理解,就是将BeanFactory的类加载器设置为Context同款。
2)setBeanExpressionResolver是为容器添加SpEL支持。Spring Expression Language(简称SpEL)在Spring3.0加入,是一种功能强大的表达式语言、用于在运行时查询和操作对象图;语法上类似于Unified EL,但提供了更多的特性,特别是方法调用和基本字符串模板函数。其用法如下:
<bean id="test" class="..."/>
<bean>
<property name="spel" value="${test}"/>
</bean>
<!--上面的配置与下面的效果一样-->
<bean id="test" class="..."/>
<bean>
<property name="spel" ref="test"/>
</bean>
当然也可以直接构造SpelExpressionParser,通过parseExpression传入SpEL表达式,然后使用getValue()取出结果。
StandardBeanExpressionResolver的构造方法中实例化了一个SpelExpressionParser对象,其evaluate方法会在Bean初始化时调用。
3)addPropertyEditorRegistar方法向容器增加了PropertyEditor注册器。以下一个例子可以说明PropertyEditor的作用:
Bean类:
public class testBean{
Date date;
...
}
配置文件:
<beans>
<bean id="test" class="testBean">
<property name="date" value="1970-01-01"/>
</bean>
</beans>
testBean在实例化时会报错,原因是XML中配置的date属性被识别为String类型,无法直接进行类型转换。
PropertyEditor有2*2,一共4种添加方法:
从配置方法来看,有编程式(context.getBeanFactory().registerCustomEditor()方法,或context.getBeanFactory().addPropertyEditorRegistrar()方法)和配置式(将自定义的PropertyEditor配置为Bean)两种;
从实现来看,有继承PropertyEditorSupport类并重写其setAsText方法,以及实现PropertyEditorRegistar接口两种。
下面是配置式的示例:
public class DatePropertyEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd");
try {
Date date=dateFormat.parse(text);
setValue(date);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
public class DatePropertyEditorRegistar 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="customEditors">
<map>
<entry key="java.util.Date">
<bean class="DatePropertyEditor"/>
</entry>
</map>
</property>
<property name="propertyEditorRegistrars">
<list>
<bean class="DatePropertyEditorRegistar"/>
</list>
</property>
</bean>
被注册的PropertyEditor会在初始化Bean时调用。
4)addBeanPostProcessor方法向容器添加了ApplicationContextAwareProcessor,用于帮助实现了某些Aware接口的Bean获取资源。主要逻辑在ApplicationContextAwareProcessor中,如果具有权限并且实现了特定借口,则调用invokeAwareInterfaces方法:
public Object postProcessBeforeInitialization(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(() -> {
this.invokeAwareInterfaces(bean);
return null;
}, acc);
} else {
this.invokeAwareInterfaces(bean);
}
return bean;
}
invokeAwareInterfaces方法就是判断传入的bean是否继承了指定的Aware接口,是则调用对应的setter方法,赋予其资源。
5)ApplicationListenerDetector顾名思义,是用来检测监听器的,Spring提供了ApplicationListener<T>接口,可以接收特定类型的事件
6)LoadTimeWeaverAwareProcessor与AspectJ有关,AspectJ weaver可以对类进行编织,然后输出为类文件。
1.2 忽略依赖接口
实现了如ApplicationContextAware等接口的Bean,在上一步中已经全部通过ApplicationContextAwareProcessor配置,因此无需再次装配,可以在DI时忽略:
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.3 注册可解析依赖
以下四个接口可以被自动装配:
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
官方的描述是:
You can also use @Autowired for interfaces that are well-known resolvable dependencies: BeanFactory , ApplicationContext , Environment , ResourceLoader , ApplicationEventPublisher , and MessageSource . These interfaces and their extended interfaces, such as ConfigurableApplicationContext or ResourcePatternResolver , are automatically resolved, with no special setup necessary. |
1.4 注册环境
这一段用到的几个方法都很熟悉了,不需要多介绍。
if (!beanFactory.containsLocalBean("environment")) {
beanFactory.registerSingleton("environment", this.getEnvironment());
}
if (!beanFactory.containsLocalBean("systemProperties")) {
beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean("systemEnvironment")) {
beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment());
}
2.invokeBeanFactoryPostProcessors
之所以跳过postProcessBeanFactory方法,是由于该方法为空,且在ClassPathXmlApplicationContext的继承链上没有覆盖。
2.1 一个例子
如上面的注释所述,invokeBeanFactoryPostProcessors方法可以赋予开发者修改已注册Bean的能力,还可以为这些BeanFactoryPostProcessor设置作用次序。下面是一个使用例子:
public class HelloBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition bean=beanFactory.getBeanDefinition("hello");
MutablePropertyValues propertyValues=bean.getPropertyValues();
propertyValues.addPropertyValue("word","Spring");
}
}
public class Hello{
String word;
Hello(){}
public void sayHello(){System.out.println("Hello "+word);}
public void setWord(String word) {this.word = word;}
}
public class Main{
public static void main(String args[]){
ApplicationContext context=new ClassPathXmlApplicationContext("config.xml");
Hello hello=(Hello)context.getBean("hello");
hello.sayHello();
}
}
配置文件为:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="hello" class="Hello">
<property name="word" value="World"/>
</bean>
<bean class="HelloBeanFactoryPostProcessor"/>
</beans>
也可以通过context.addBeanFactoryPostProcessor()方法配置。运行后,输出的不是“Hello World”,而是“Hello Spring”。
2.2核心方法介绍
invokeBeanFactoryPostProcessors的核心方法是invokeBeanFactoryPostProcessors,该方法长达130多行,因此分段进行解释。
首先,会先判断传入的beanFactory是否是BeanDefinitionRegistry,从DefaultListableBeanFactory的继承关系来看,答案是肯定的。然后就从传入的BeanFactoryPostProcessor列表中读取每个元素,判断是否是BeanDefinitionRegistryPostProcessor类型,然后分别进行注册。
BeanDefinitionRegistry registry = (BeanDefinitionRegistry)beanFactory;
regularPostProcessors = new ArrayList();
registryProcessors = new ArrayList();
Iterator var6 = beanFactoryPostProcessors.iterator();
while(var6.hasNext()) {
BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor)var6.next();
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor)postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
} else {
regularPostProcessors.add(postProcessor);
}
}
接下来,优先处理实现了PriorityOrdered或Ordered接口的元素(两段差不多,所以只列出PriorityOrdered的)。getBeanNamesForType方法就是从BeanFactory中根据PostProcessor的类型来查找BeanName。也就是说,上面一段用的BeanFactoryPostProcessor列表,并不包含XML配置的后处理器:
currentRegistryProcessors = new ArrayList();
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
String[] var16 = postProcessorNames;
var9 = postProcessorNames.length;
int var10;
String ppName;
for(var10 = 0; var10 < var9; ++var10) {
ppName = var16[var10];
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
invokeBeanDefinitionRegistryPostProcessors实际就是调用BeanDefinitionRegistryPostProcessor实现类的postProcessBeanDefinitionRegistry方法。
对于那些未实现PriorityOrdered或Ordered接口的元素,在接下来的循环里进行处理:
boolean reiterate = true;
while(reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
String[] var19 = postProcessorNames;
var10 = postProcessorNames.length;
for(int var26 = 0; var26 < var10; ++var26) {
String ppName = var19[var26];
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();
}
上面的代码里,仅仅处理了BeanDefinitionRegistryPostProcessor,对于BeanFactoryPostProcessors还没有处理,会在这里统一进行处理,实际就是调用BeanFactoryPostProcessor实现类的postProcessBeanFactory方法。:
invokeBeanFactoryPostProcessors((Collection)registryProcessors, (ConfigurableListableBeanFactory)beanFactory);
invokeBeanFactoryPostProcessors((Collection)regularPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
如果传入的beanFactory并不是是BeanDefinitionRegistry,则直接调用invokeBeanFactoryPostProcessors(Collection,ConfigurableListableBeanFactory)方法。
上面一部分,处理了所有的BeanDefinitionRegistryPostProcessor和编程式配置的BeanFactoryPostProcessors,但是XML配置的BeanFactoryPostProcessor还没处理,后面的代码就是进行这部分工作。逻辑和上面的类似。
3.registerBeanPostProcessors
上一步完成了BeanFactoryPostProcessor的注册和调用,这一步的工作就是进行BeanPostProcessor的注册(未调用,调用过程发生在Bean实例化时)。在prepareBeanFactory方法中,实际上已经注册了一部分特殊的(实现了Aware接口)Bean。与BeanFactoryPostProcessor一样,该方法同样借助了PostProcessorRegistrationDelegate类。
因此两个方法代码也差不多,都是先处理实现PriorityOrdered或Ordered接口的元素,再处理普通元素,唯二的区别是:1.此处是仅考虑了XML配置的BeanPostProcessor;2.此处只进行了注册(register),而非调用(invoke)。结合来看,BeanFactoryPostProcessor是提取并调用,因此需要将两种配置方式全部考虑, 而这里BeanPostProcessor仅仅进行了注册,还不需要考虑调用,因此无需处理API配置的后处理器。
一个有意思的地方是,在所有BeanPostProcessor之前,添加了一个BeanPostProcessorChecker。它的作用是检查配置的BeanPostProcessor是否已经被实例化。上一步调用BeanFactoryPostProcessor可以修改Bean的行为,如果此时尝试获取Bean,就可能导致它们提前实例化。作为Bean的一种,BeanPostProcessor也有可能已经被实例化过了,那么当BeanPostProcessor实例化时,就不需要再次实例化了。
beanFactory.addBeanPostProcessor(new PostProcessorRegistrationDelegate.BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));