前言
通过上一讲,我们知道AbstractApplicationContext类的refresh方法,是Spring IOC的入口方法。
该方法包含了很多其他的方法,这些方法的主要功能如下:

initPropertySources方法是一个钩子方法,给子类实现的,子类AnnotationConfigServletWebApplicationContext的prepareRefresh方法,最终会调用AbstractApplicationContext类的prepareRefresh方法。
这该方法会初始化placeholder属性,我们可以向Environment中添加属性值,也可以校验Environment中的属性。
这个方法不是今天的重点,今天的重点是obtainFreshBeanFactory方法。
Spring通过该方法创建Bean工厂,读取applicationContext.xml等配置文件中定义的各种配置标签。
1. 如何创建Bean工厂?
obtainFreshBeanFactory方法的只包含下面两行代码:
protectedConfigurableListableBeanFactoryobtainFreshBeanFactory(){
refreshBeanFactory();
returngetBeanFactory();
}其中refreshBeanFactory方法是核心方法,重点看AbstractApplicationContex的子类AbstractRefreshableApplicationContext类的refreshBeanFactory方法:
protectedfinalvoidrefreshBeanFactory()throwsBeansException{
//判断是否存在beanFactory容器
if(hasBeanFactory()){
//销毁beanFactory容器,清空缓存
destroyBeans();
//清空beanFactory容器
closeBeanFactory();
}
try{
//创建beanFactory容器
DefaultListableBeanFactorybeanFactory=createBeanFactory();
//设置序列化id
beanFactory.setSerializationId(getId());
//用户可自定义beanFactory容器的参数
customizeBeanFactory(beanFactory);
//真正解析配置文件的地方
loadBeanDefinitions(beanFactory);
//赋值beanFactory
this.beanFactory=beanFactory;
}
catch(IOExceptionex){
thrownewApplicationContextException("I/Oerrorparsingbeandefinitionsourcefor"+getDisplayName(),ex);
}
}这个方法的逻辑也非常清晰,在创建beanFactory容器之前,先判断一下beanFactory容器对象是否存在,如果存在,则先销毁已有的容器,清空相关缓存,再创建新的beanFactory容器。
创建beanFactory容器简单粗暴:
protectedDefaultListableBeanFactorycreateBeanFactory(){
returnnewDefaultListableBeanFactory(getInternalParentBeanFactory());
}直接new了一个DefaultListableBeanFactory类的实例对象。其中getInternalParentBeanFactory方法可以获取父beanFactory容器对象,在Spring中容器是可以嵌套的。
2.模板方法模式
看了前面的这些代码,不知道你有没有发现Spring用了大量的模板方法模式。
这个模式非常有用,我在实际工作中也经常使用该设计模式。
模板方法模式是这样的:
publicabstractclassPepole{
publicabstracvoidbefore();
publicvoiddoSamething(){
before();
System.out.println("==doSamething==")
after();
}
publicabstracvoidafter();
}
publicclassStudentextendsPepole{
@Override
publicvoidbefore(){
System.out.println("==before==")
}
@Override
publicvoidafter(){
System.out.println("==after==")
}
}在abstract类中可以定义了一个或多个abstract方法,在该abstract类的非abstract方法中,比如:doSamething方法中,调用了before和after这两个abstract方法。
这样做的目的是:类定义成abstract,是为了不能直接创建对象,而必须交给该类的子类来创建对象。
同时在非abstract方法,即doSamething方法中,可以定义代码的执行流程。先执行before方法,再做业务处理,再执行after方法。
而before方法和after方法的逻辑,交给子类去实现,这样可以增加代码的扩展性。
我们再看看Spring是如何实现模板方法模式的:
publicabstractclassAbstractApplicationContextextendsDefaultResourceLoader
implementsConfigurableApplicationContext{
protectedConfigurableListableBeanFactoryobtainFreshBeanFactory(){
refreshBeanFactory();
returngetBeanFactory();
}
protectedabstractvoidrefreshBeanFactory()throwsBeansException,IllegalStateException;
}
publicabstractclassAbstractRefreshableApplicationContextextendsAbstractApplicationContext{
@Override
protectedfinalvoidrefreshBeanFactory()throwsBeansException{
if(hasBeanFactory()){
destroyBeans();
closeBeanFactory();
}
try{
DefaultListableBeanFactorybeanFactory=createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
this.beanFactory=beanFactory;
}
catch(IOExceptionex){
thrownewApplicationContextException("I/Oerrorparsingbeandefinitionsourcefor"+getDisplayName(),ex);
}
}
}模板方法模式,建议大家在实际工作中用起来,可以让代码变得更优雅一些。
3.自定义beanFactory参数
通过上面创建好beanFactory之后,可以给该beanFactory设置一个serializationId,即序列化id。
然后通过customizeBeanFactory方法给beanFactory设置用户自定义参数:
protectedvoidcustomizeBeanFactory(DefaultListableBeanFactorybeanFactory){
if(this.allowBeanDefinitionOverriding!=null){
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if(this.allowCircularReferences!=null){
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}目前beanFactory全局的用户自定义参数有两个:
- allowBeanDefinitionOverriding:是否允许注册同名的bean,默认值是true。
- allowCircularReferences:是否自动尝试解决循环依赖,默认值是true。
其实这两个参数一般情况下用默认值就够了,很少会调整的。
接下来的loadBeanDefinitions方法,是创建Bean的关键方法,这个方法的内容比较多,我们下期分享。
最后getBeanFactory方法返回当前创建的beanFactory对象。