spring源码学习笔记-初始化(二)-BeanFactory

转自http://www.sandzhang.com/blog/2011/04/02/spring-study-notes-initialization-2/

上篇结束的地方简单介绍了一下refresh()方法,现在我们具体分析一下它的代码细节:

1.首先可以看到整个refresh()的代码都是同步的,对应的同步对象是startupShutdownMonitor,我们看一下startupShutdownMonitor引用的地方,可以知道,只有在refresh()和close()两个方法里用到,说明这个锁是用来同步applicationContext的刷新和销毁的。

2.同步代码块的第一行是prepareRefresh()方法,代码如下:


 

  1. protected void prepareRefresh() { 
  2.     this.startupDate = System.currentTimeMillis(); 
  3.     synchronized (this.activeMonitor) { 
  4.         this.active = true
  5.     } 
  6.     if (logger.isInfoEnabled()) { 
  7.         logger.info("Refreshing " + this); 
  8.     } 
protected void prepareRefresh() {
    this.startupDate = System.currentTimeMillis();
    synchronized (this.activeMonitor) {
        this.active = true;
    }
    if (logger.isInfoEnabled()) {
        logger.info("Refreshing " + this);
    }
}


 

这个方法也很简单

  1. 首先设置startupDate为系统当前毫秒数,代表当前applicationContext的创建时间;
  2. 设置active为true,代表当前applicationContext是活动的,可以看到对active的赋值操作是同步的,同步对象为activeMonitor,查看active的引用点,可以看到所有对 active的操作都是同步在activeMonitor下的,在调用cancelRefresh()和doClose()两个方法的时候会把它设置为false,其中cancelRefresh()代表中止refresh,doClose()则是当前applicationContext的关闭销毁方法
  3. 最后是日志的打印,info级别,我这里要说的一点是后面直接+this,代表会调用toString方法,AbstractApplicationContext重写了toString,大概格式是displayName+startup+parent displayName

3.接着是这一行:ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(),obtainFreshBeanFactory代码如下:

  1. protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { 
  2.     refreshBeanFactory(); 
  3.     ConfigurableListableBeanFactory beanFactory = getBeanFactory(); 
  4.     if (logger.isDebugEnabled()) { 
  5.         logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); 
  6.     } 
  7.     return beanFactory; 
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (logger.isDebugEnabled()) {
        logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
    }
    return beanFactory;
}


 

第一行调用refreshBeanFactory(),我们先跳过这行看下面,调用了getBeanFactory()获得beanFactory对象然后返回这个对象,看getBeanFactory()的代码可以看到,是做了一个同步,然后取出当前对象里的beanFactory,同步锁是beanFactoryMonitor:

注:refreshBeanFactory()和getBeanFactory()方法在AbstractRefreshableApplicationContext类里面,关于ApplicationContext的类结构我会在另外一篇文章里做专门介绍,请看:ApplicationContext的类继承结构及框架图


 

  1. public final ConfigurableListableBeanFactory getBeanFactory() { 
  2.     synchronized (this.beanFactoryMonitor) { 
  3.         if (this.beanFactory == null) { 
  4.             throw new IllegalStateException("BeanFactory not initialized or already closed - "
  5.                     "call 'refresh' before accessing beans via the ApplicationContext"); 
  6.         } 
  7.         return this.beanFactory; 
  8.     } 
public final ConfigurableListableBeanFactory getBeanFactory() {
    synchronized (this.beanFactoryMonitor) {
        if (this.beanFactory == null) {
            throw new IllegalStateException("BeanFactory not initialized or already closed - " +
                    "call 'refresh' before accessing beans via the ApplicationContext");
        }
        return this.beanFactory;
    }
}


如果beanFactory为空则会抛出异常,其实一开始beanFactory肯定是null的,beanFactory的创建就是在refreshBeanFactory()方法中,下面我们看它的代码:

  1. protected final void refreshBeanFactory() throws BeansException { 
  2.     if (hasBeanFactory()) { 
  3.         destroyBeans(); 
  4.         closeBeanFactory(); 
  5.     } 
  6.     try
  7.         DefaultListableBeanFactory beanFactory = createBeanFactory(); 
  8.         beanFactory.setSerializationId(getId()); 
  9.         customizeBeanFactory(beanFactory); 
  10.         loadBeanDefinitions(beanFactory); 
  11.         synchronized (this.beanFactoryMonitor) { 
  12.             this.beanFactory = beanFactory; 
  13.         } 
  14.     } 
  15.     catch (IOException ex) { 
  16.         throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); 
  17.     } 
protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        customizeBeanFactory(beanFactory);
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}


 

前面3行代码首先判断是否hasBeanFactory(),如果存在则调用destroyBeans()以及closeBeanFactory():

  • hasBeanFactory()是在判断属性beanFactory是否为空,当然同上面一样beanFactory的操作是同步的,同步对象是beanFactoryMonitor。
  • destroyBeans()方法只有一行代码:getBeanFactory().destroySingletons(),调用了beanFactory对象的destroySingletons()方法来销毁所有单例bean。(后面还会用到这个方法,放到后面详细介绍)
  • closeBeanFactory()和上面一样,依旧是同步的情况下处理beanFactory属性,首先调用setSerializationId(null),然后把beanFactory属性设置为null。

接下来后面的代码是一个创建beanFactory的过程:

  • 调用createBeanFactory()方法创建一个beanFactory对象:
    查看方法代码可以看到创建的是一个DefaultListableBeanFactory对象,参数parent传递的方法getInternalParentBeanFactory()返回的结果,getInternalParentBeanFactory()方法的代码为:
    (getParent() instanceof ConfigurableApplicationContext) ? ((ConfigurableApplicationContext) getParent()).getBeanFactory() : getParent()
    如果当前applicationContext对象的parent是ConfigurableApplicationContext类的实例则返回当前对象的parent的beanFactory对象,否则直接返回当前对象的parent。
  • 将当前对象的id属性作为参数调用为beanFactory对象的setSerializationId()方法,我们这里看下这个方法的代码:
  1. public void setSerializationId(String serializationId) { 
  2.     if (serializationId != null) { 
  3.         serializableFactories.put(serializationId, 
  4.                 new WeakReference<DefaultListableBeanFactory>(this)); 
  5.     } else if (this.serializationId != null) { 
  6.         serializableFactories.remove(this.serializationId); 
  7.     } 
  8.     this.serializationId = serializationId; 
public void setSerializationId(String serializationId) {
    if (serializationId != null) {
        serializableFactories.put(serializationId,
                new WeakReference<DefaultListableBeanFactory>(this));
    } else if (this.serializationId != null) {
        serializableFactories.remove(this.serializationId);
    }
    this.serializationId = serializationId;
}


 

  • 首先,输入参数如果不为空执行(1),否则再判断如果当前对象的属性serializationId不为空,执行(2)
    (1)在serializableFactories里加入一组值:键为serializationId,值为当前对象的弱引用
    (2)从serializableFactories中移除键为当前对象属性serializationId的对象,也就是以前存入的当前对象的弱引用
    (3)设置属性serializationId为输入参数
  • customizeBeanFactory()方法的代码:


 

  1. protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) { 
  2.     if (this.allowBeanDefinitionOverriding != null) { 
  3.         beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); 
  4.     } 
  5.     if (this.allowCircularReferences != null) { 
  6.         beanFactory.setAllowCircularReferences(this.allowCircularReferences); 
  7.     } 
  8.     beanFactory.setParameterNameDiscoverer(new LocalVariableTableParameterNameDiscoverer()); 
  9.     beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver()); 
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
    if (this.allowBeanDefinitionOverriding != null) {
        beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }
    if (this.allowCircularReferences != null) {
        beanFactory.setAllowCircularReferences(this.allowCircularReferences);
    }
    beanFactory.setParameterNameDiscoverer(new LocalVariableTableParameterNameDiscoverer());
    beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
}


 

  • 如果属性allowBeanDefinitionOverriding不为空,设置给beanFactory对象相应属性,此属性的含义:是否允许覆盖同名称的不同定义的对象
    如果属性allowCircularReferences不为空,设置给beanFactory对象相应属性,此属性的含义:是否允许bean之间循环引用
    设置beanFactory的parameterNameDiscoverer属性为一个新的LocalVariableTableParameterNameDiscoverer对象,主要用asm解析class文件
    设置beanFactory的parameterNameDiscoverer属性为一个新的QualifierAnnotationAutowireCandidateResolver对象,主要用于自动装配的处理
  • loadBeanDefinitions()方法的代码:
  1. protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { 
  2.     XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); 
  3.     beanDefinitionReader.setResourceLoader(this); 
  4.     beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); 
  5.     initBeanDefinitionReader(beanDefinitionReader); 
  6.     loadBeanDefinitions(beanDefinitionReader); 
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
    initBeanDefinitionReader(beanDefinitionReader);
    loadBeanDefinitions(beanDefinitionReader);
}


 

  • 第1行创建XmlBeanDefinitionReader对象
    第2行设置beanDefinitionReader的resourceLoader属性为当前对象
    第3行设置beanDefinitionReader的entityResolver属性为一个新的ResourceEntityResolver对象,输入参数resourceLoader为当前对象,这个数要是用来解析xml的
    第4行设置beanDefinitionReader的validationMode以及namespaceAware,参数是当前对象的validating属性,主要用于xml校检
    最后一行是做了xml配置文件的读取,就不做详细描述了,有个细节是会循环加载configResources、configLocations两个里面的文件
  • 接着是同步操作beanFactory,把创建的beanFactory对象赋值给当前ApplicationContext的beanFactory属性

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值