前言

通过上一讲,我们知道AbstractApplicationContext类的refresh方法,是Spring IOC的入口方法。

该方法包含了很多其他的方法,这些方法的主要功能如下:

image

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全局的用户自定义参数有两个:

  1. allowBeanDefinitionOverriding:是否允许注册同名的bean,默认值是true。
  2. allowCircularReferences:是否自动尝试解决循环依赖,默认值是true。

其实这两个参数一般情况下用默认值就够了,很少会调整的。

接下来的loadBeanDefinitions方法,是创建Bean的关键方法,这个方法的内容比较多,我们下期分享。

最后getBeanFactory方法返回当前创建的beanFactory对象。

最后修改:2026 年 06 月 05 日
如果觉得我的文章对你有用,请随意赞赏