初学Spring源码3.2:obtainFreshBeanFactory()

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()
这个方法一共做了两件事:

  • 创建一个BeanFactory(DefaultListableBeanFactory类型),并将其设置为当前应用上下文的实例变量
  • 创建了一个或多个BeanDefinitionReader(设置了Environment和ResourceLoader等参数),将在BeanDefinition信息到BeanFactory中
/**
 * Tell the subclass to refresh the internal bean factory.
 * @return the fresh BeanFactory instance
 * @see #refreshBeanFactory()
 * @see #getBeanFactory()
 */
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   // 由子类创建BeanFactory
   refreshBeanFactory();
   // 取得子类创建好的BeanFactory
   return getBeanFactory();
}

AbstractApplicationContext中的**refreshBeanFactory()**方法是抽象方法,具体实现是由AbstractRefreshableApplicationContext实现

/**
 * 实际执行上下文底层的Bean Factory刷新的实现,清除之前(如果存在的话)任何存在的Bean Factory并初始化一个新的
 * BeanFactory用于上下文生命周期的下一阶段
 * This implementation performs an actual refresh of this context's underlying
 * bean factory, shutting down the previous bean factory (if any) and
 * initializing a fresh bean factory for the next phase of the context's lifecycle.
 */
@Override
protected final void refreshBeanFactory() throws BeansException {
   // 如果BeanFactory已经存在,就销毁context管理的所有bean,并关闭BeanFactory
   if (hasBeanFactory()) {
      // 其实就是调用一些集合的clear方法,解除对一些实例的引用,参考
      // DefaultSingletonBeanRegistry.destroySingletons方法
      destroyBeans();
      // 关闭当前的beanFactory,其实就是将成员变量beanFactory设置为null
      closeBeanFactory();
   }
   try {
      // 为上下文创建一个BeanFactory作为其内部的实例变量
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      customizeBeanFactory(beanFactory);
      loadBeanDefinitions(beanFactory);
      this.beanFactory = beanFactory;
   }
   catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}

DefaultListableBeanFactory beanFactory = createBeanFactory();

/**
 * 为上下文创建一个BeanFactory作为其内部的实例变量
 * Create an internal bean factory for this context. 
 * Called for each {@link #refresh()} attempt.
 * <p>The default implementation creates a
 * {@link org.springframework.beans.factory.support.DefaultListableBeanFactory}
 * with the {@linkplain #getInternalParentBeanFactory() internal bean factory} of this
 * context's parent as parent bean factory. Can be overridden in subclasses,
 * for example to customize DefaultListableBeanFactory's settings.
 * @return the bean factory for this context
 * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowBeanDefinitionOverriding
 * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowEagerClassLoading
 * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowCircularReferences
 * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowRawInjectionDespiteWrapping
 */
protected DefaultListableBeanFactory createBeanFactory() {
   return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}

new DefaultListableBeanFactory(getInternalParentBeanFactory())最终会在AbstractAutowireCapableBeanFactory实现,

返回一个DefaultListableBeanFactory类型的BeanFactory

/**
 * Create a new AbstractAutowireCapableBeanFactory.
 */
public AbstractAutowireCapableBeanFactory() {
   super();
   ignoreDependencyInterface(BeanNameAware.class);
   ignoreDependencyInterface(BeanFactoryAware.class);
   ignoreDependencyInterface(BeanClassLoaderAware.class);
}

customizeBeanFactory(beanFactory);

/**
 * 定制这个上下文使用的内部bean factory,设置了是否重新定义bean信息和是否允许bean循环引用两个boolean型参数
 * Customize the internal bean factory used by this context.
 * Called for each {@link #refresh()} attempt.
 * <p>The default implementation applies this context's
 * {@linkplain #setAllowBeanDefinitionOverriding "allowBeanDefinitionOverriding"}
 * and {@linkplain #setAllowCircularReferences "allowCircularReferences"} settings,
 * if specified. Can be overridden in subclasses to customize any of
 * {@link DefaultListableBeanFactory}'s settings.
 * @param beanFactory the newly created bean factory for this context
 * @see DefaultListableBeanFactory#setAllowBeanDefinitionOverriding
 * @see DefaultListableBeanFactory#setAllowCircularReferences
 * @see DefaultListableBeanFactory#setAllowRawInjectionDespiteWrapping
 * @see DefaultListableBeanFactory#setAllowEagerClassLoading
 */
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
   // 此时,this.allowBeanDefinitionOverriding和this.allowCircularReferences均为null,
   // 所以不会设置
   if (this.allowBeanDefinitionOverriding != null) {
      beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
   }
   if (this.allowCircularReferences != null) {
      beanFactory.setAllowCircularReferences(this.allowCircularReferences);
   }
}
/**
 * 通过设置一个的值,来作为判断是否允许重写bean定义的标志
 * 如果allowBeanDefinitionOverriding为true,当注册一个相同名称的不同定义(同名的类)时,后者自动覆盖前者
 * 如果allowBeanDefinitionOverriding为false,则抛出一个异常
 * 默认为true
 * Set whether it should be allowed to override bean definitions by registering
 * a different definition with the same name, automatically replacing the former.
 * If not, an exception will be thrown. Default is "true".
 * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowBeanDefinitionOverriding
 */
public void setAllowBeanDefinitionOverriding(boolean allowBeanDefinitionOverriding) {
   this.allowBeanDefinitionOverriding = allowBeanDefinitionOverriding;
}
/**
 * 设置bean之间是否允许循环引用,并且自动尝试解决它们,默认是true,关闭此选项会完全禁止循环应用
 * 并且在发生错误后将会抛出异常
 * Set whether to allow circular references between beans - and automatically
 * try to resolve them.
 * <p>Default is "true". Turn this off to throw an exception when encountering
 * a circular reference, disallowing them completely.
 * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowCircularReferences
 */
public void setAllowCircularReferences(boolean allowCircularReferences) {
   this.allowCircularReferences = allowCircularReferences;
}

loadBeanDefinitions(beanFactory);

/**
 * 通过委托给一个或多个beanDefinitionReader读取bean信息到给定的BeanFactory
 * Load bean definitions into the given bean factory, typically through
 * delegating to one or more bean definition readers.
 * @param beanFactory the bean factory to load bean definitions into
 * @throws BeansException if parsing of the bean definitions failed
 * @throws IOException if loading of bean definition files failed
 * @see org.springframework.beans.factory.support.PropertiesBeanDefinitionReader
 * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
 */
protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
      throws BeansException, IOException;

是由AbstractXmlApplicationContext中实现

/**
 * Loads the bean definitions via an XmlBeanDefinitionReader.
 * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
 * @see #initBeanDefinitionReader
 * @see #loadBeanDefinitions
 */
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
   // Create a new XmlBeanDefinitionReader for the given BeanFactory.
   // 为给定的beanFactory创建一个新的XmlBeanDefinitionReader
   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

   // Configure the bean definition reader with this context's
   // resource loading environment.
   // 为BeanDefinitionReader设置这个上下文的Environment和ResourceLoader
   beanDefinitionReader.setEnvironment(this.getEnvironment());
   beanDefinitionReader.setResourceLoader(this);
   beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

   // Allow a subclass to provide custom initialization of the reader,
   // then proceed with actually loading the bean definitions.
   // 允许子类提供一个一个特殊的设置的BeanDefinitionReader用来加载BeanDefinition
   // BeanDefinitionReader初始化完成后开始加载BeanDefinition
   initBeanDefinitionReader(beanDefinitionReader);
   loadBeanDefinitions(beanDefinitionReader);
}

new XmlBeanDefinitionReader(beanFactory)

/**
 * Create new XmlBeanDefinitionReader for the given bean factory.
 * @param registry the BeanFactory to load bean definitions into,
 * in the form of a BeanDefinitionRegistry
 */
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
   super(registry);
}

调用父类的构造方法,创建了一个AbstractBeanDefinitionReader类型的BeanDefinitionReader

/**
 * 为给定的bean factory创建一个新的AbstractBeanDeifinitionReader
 * 如果传入的bean factory不止实现了BeanDefinitionRegistry接口,也实现了ResourceLoader接口
 * 那这个bean factory将会被用作默认的ResourceLoader,这种情况通常是ApplicationContext的实现类
 * 如果传入传入的bean factory仅实现了BeanDefinitionRegistry接口,默认的ResourceLoader将会是
 * PathMatchingResourcePatternResolver
 * 如果传入的bean factory也实现了EnvironmentCapable接口,这个BeanDefinitionReader将使用它的environment
 * 其它情况下,这个BeanDefinitionReader将会使用一个StardardEnvironment进行初始化.所有的ApplicationContext
 * 的实现类都是支持Environment的,而普通的BeanFactory则不支持
 *
 * 说白了这里列了BeanDefinitionReader的两个参数的取值情况
 * ResourceLoader和Environment
 * Create a new AbstractBeanDefinitionReader for the given bean factory.
 * <p>If the passed-in bean factory does not only implement the BeanDefinitionRegistry
 * interface but also the ResourceLoader interface, it will be used as default
 * ResourceLoader as well. This will usually be the case for
 * {@link org.springframework.context.ApplicationContext} implementations.
 * <p>If given a plain BeanDefinitionRegistry, the default ResourceLoader will be a
 * {@link org.springframework.core.io.support.PathMatchingResourcePatternResolver}.
 * <p>If the passed-in bean factory also implements {@link EnvironmentCapable} its
 * environment will be used by this reader.  Otherwise, the reader will initialize and
 * use a {@link StandardEnvironment}. All ApplicationContext implementations are
 * EnvironmentCapable, while normal BeanFactory implementations are not.
 * @param registry the BeanFactory to load bean definitions into,
 * in the form of a BeanDefinitionRegistry
 * @see #setResourceLoader
 * @see #setEnvironment
 */
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
   Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
   this.registry = registry;

   // Determine ResourceLoader to use.
   if (this.registry instanceof ResourceLoader) {
      this.resourceLoader = (ResourceLoader) this.registry;
   }
   else {
      this.resourceLoader = new PathMatchingResourcePatternResolver();
   }

   // Inherit Environment if possible
   if (this.registry instanceof EnvironmentCapable) {
      this.environment = ((EnvironmentCapable) this.registry).getEnvironment();
   }
   else {
      this.environment = new StandardEnvironment();
   }
}

loadBeanDefinitions(beanDefinitionReader);

/**
 * 使用给定的BeanDefinitionReader加载bean的定义信息
 * 由于bean factory的声明周期由AbstractRefreshableApplicationContext的refreshBeanFactory方法负责
 * 因此这个loadBeanDefinitions方法仅支持加载和注册BeanDefinition
 * Load the bean definitions with the given XmlBeanDefinitionReader.
 * <p>The lifecycle of the bean factory is handled by the {@link #refreshBeanFactory}
 * method; hence this method is just supposed to load and/or register bean definitions.
 * @param reader the XmlBeanDefinitionReader to use
 * @throws BeansException in case of bean registration errors
 * @throws IOException if the required XML document isn't found
 * @see #refreshBeanFactory
 * @see #getConfigLocations
 * @see #getResources
 * @see #getResourcePatternResolver
 */
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
   Resource[] configResources = getConfigResources();
   if (configResources != null) {//此时为null
      reader.loadBeanDefinitions(configResources);
   }
   String[] configLocations = getConfigLocations();
   if (configLocations != null) {
      reader.loadBeanDefinitions(configLocations);
   }
}

reader.loadBeanDefinitions(configLocations);

@Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
   Assert.notNull(locations, "Location array must not be null");
   int count = 0;
   for (String location : locations) {
      count += loadBeanDefinitions(location);
   }
   return count;
}

count += loadBeanDefinitions(location);

@Override
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
   return loadBeanDefinitions(location, null);
}

loadBeanDefinitions(location, null);

/**
 * 从给定的源位置路径加载beanDefinition
 * 这个路径也可以时路径模式,前提时这个BeanDefinitionReader的ResourceLoader是一个ResourcePatternResolver
 * Load bean definitions from the specified resource location.
 * <p>The location can also be a location pattern, provided that the
 * ResourceLoader of this bean definition reader is a ResourcePatternResolver.
 * @param location the resource location, to be loaded with the ResourceLoader
 * (or ResourcePatternResolver) of this bean definition reader
 * @param actualResources a Set to be filled with the actual Resource objects
 * that have been resolved during the loading process. May be {@code null}
 * to indicate that the caller is not interested in those Resource objects.
 * @return the number of bean definitions found
 * @throws BeanDefinitionStoreException in case of loading or parsing errors
 * @see #getResourceLoader()
 * @see #loadBeanDefinitions(org.springframework.core.io.Resource)
 * @see #loadBeanDefinitions(org.springframework.core.io.Resource[])
 */
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
   ResourceLoader resourceLoader = getResourceLoader();
   if (resourceLoader == null) {
      throw new BeanDefinitionStoreException(
            "Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
   }

   if (resourceLoader instanceof ResourcePatternResolver) {
      // Resource pattern matching available.
      try {
         Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
         int count = loadBeanDefinitions(resources);
         if (actualResources != null) {
            Collections.addAll(actualResources, resources);
         }
         if (logger.isTraceEnabled()) {
            logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
         }
         return count;
      }
      catch (IOException ex) {
         throw new BeanDefinitionStoreException(
               "Could not resolve bean definition resource pattern [" + location + "]", ex);
      }
   }
   else {
      // Can only load single resources by absolute URL.
      Resource resource = resourceLoader.getResource(location);
      int count = loadBeanDefinitions(resource);
      if (actualResources != null) {
         actualResources.add(resource);
      }
      if (logger.isTraceEnabled()) {
         logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
      }
      return count;
   }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值