切入点:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
跟踪进入其构造器源码:
public ClassPathXmlApplicationContext(String[] configLocations,boolean refresh,ApplicationContext parent){
super();
/*
ClassPathXmlApplicationContext可以将配置文件以字符串数组的方式传入
也就是可以同时传入多个配置文件的路径
*/
setConfiglocations(configLocations);
if(refresh){
refresh();
}
}
解析配置文件:
public void setConfigLocations(String[] locations){
if(locations != null){
this.configLocations = new String[locations.length];
for(int i = 0;i < locations.length;i++){
//解析路径
//如果原始路径中有spel表达式(${location})、特殊符号,这里会寻找相应变量进行替换
this.configLocations[i] = resolvePath(locations[i].trim());
}
}else{
this.configLocations = null;
}
}
根据解析的配置文件刷新容器:
public void refresh(){
synchronized(this.startupShutdownMonitor){
//准备刷新容器的上下文环境
prepareRefresh();
//初始化BeanFactory,并进行XML读取
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//对BeanFactory进行功能填充
prepareBeanFactory();
//如果设置了beanFactory处理器组件,在此处进行组装
postProcessBeanFactory(beanFactory(beanFactory);
//激活各种beanFactory的处理器
invokeBeanFactoryPostProcessors(beanFactory);
//注册拦截Bean创建的Bean处理器,这里只是将其注册机进来,调用是在getBean的时候调用
registerBeanPostProcessors(beanFactory);
//国际化处理
initMessageSource();
//初始化应用消息广播器
initApplicationEventMulticaster();
//留给子类来初始化其他的bean
onRefresh();
//注册监听器
rgisterListeners();
//注册遗留的bean
finishRefresh();
destroyBeans();
cancelRefresh();
}
}
下面将对上述代码一一进行讲述
1.环境准备:prepareRefresh方法
入口代码:
protected void prepareRefresh(){
this.startupDate = System.cuuentTimeMillis();
synchronized(this.activeMonitor){
this.active = true;
}
//模板方法,留给子类实现
initPropertySources();
//验证需要的属性文件是否都已经放入环境中
getEnvironment().validateRequiredProperties();
}
这两个方法可以搭配起来使用:
比如某个工程需要环境参数中有pro这个变量,但是实际上并没有,所以我们可以自定义类来实现:
public class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext{
//添加验证要求
protected void initPropertySources(){
getEnvironment.setRequiredProperties("pro");
}
public static void main(String[] args){
ApplicationContext context = new MyClassPathXmlApplicationContext("applicationContext.xml");
}
}
2.加载BeanFactory:obtainFreshBeanFactory方法
经过obtainFreshBeanFactory方法后,ApplicationContext就具有了BeanFactory的所有功能
protected ConfigurableListableBeanFactory obtainFreshBeanFactory(){
//初始化BeanFactory,读取xml文件,并将实例化的BeanFactory记录在当前实体的属性中
refreshBeanFactory();
//getBeanFactory返回的就是上一步记录在实体属性中的beanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
return beanFactory;
}
protected final void refreshBeanFactory(){
if(hasBeanFactory()){
destroyBeans();
closeBeanFactory();
}
//创建DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
//为了序列化指定的id,如果需要的话,让这个BeanFactory从id反序列化到beanFactory对象
beanFactory.setSerializationId(getId());
//定制beanFactory
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
//使用全局变量记录beanFactory
synchronized(this.beanFactroyMonitor){
this.beanFactory = beanFactory;
}
}
beanFactory功能扩展:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory){
//设置beanFactory的classLoader为当前context的classLoader
beanFactory.setBeanClassLoader(getClassLoader());
//设置beanFactory的表达式语言处理器(spring3增加了表达式语言的支持)
//默认可以使用#{bean.xxx}的形式来调用相关属性值
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
...
}