Package org.springframework.context.support

Source Code of org.springframework.context.support.AbstractRefreshableApplicationContext

/*
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.context.support;

import java.io.IOException;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextException;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;

/**
* Base class for {@link org.springframework.context.ApplicationContext}
* implementations which are supposed to support multiple calls to {@link #refresh()},
* creating a new internal bean factory instance every time.
* Typically (but not necessarily), such a context will be driven by
* a set of config locations to load bean definitions from.
*
* <p>The only method to be implemented by subclasses is {@link #loadBeanDefinitions},
* which gets invoked on each refresh. A concrete implementation is supposed to load
* bean definitions into the given
* {@link org.springframework.beans.factory.support.DefaultListableBeanFactory},
* typically delegating to one or more specific bean definition readers.
*
* <p><b>Note that there is a similar base class for WebApplicationContexts.</b>
* {@link org.springframework.web.context.support.AbstractRefreshableWebApplicationContext}
* provides the same subclassing strategy, but additionally pre-implements
* all context functionality for web environments. There is also a
* pre-defined way to receive config locations for a web context.
*
* <p>Concrete standalone subclasses of this base class, reading in a
* specific bean definition format, are {@link ClassPathXmlApplicationContext}
* and {@link FileSystemXmlApplicationContext}, which both derive from the
* common {@link AbstractXmlApplicationContext} base class;
* {@link org.springframework.context.annotation.AnnotationConfigApplicationContext}
* supports {@code @Configuration}-annotated classes as a source of bean definitions.
*
* @author Juergen Hoeller
* @author Chris Beams
* @since 1.1.3
* @see #loadBeanDefinitions
* @see org.springframework.beans.factory.support.DefaultListableBeanFactory
* @see org.springframework.web.context.support.AbstractRefreshableWebApplicationContext
* @see AbstractXmlApplicationContext
* @see ClassPathXmlApplicationContext
* @see FileSystemXmlApplicationContext
* @see org.springframework.context.annotation.AnnotationConfigApplicationContext
*/
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {

  private Boolean allowBeanDefinitionOverriding;

  private Boolean allowCircularReferences;

  /** Bean factory for this context */
  private DefaultListableBeanFactory beanFactory;

  /** Synchronization monitor for the internal BeanFactory */
  private final Object beanFactoryMonitor = new Object();


  /**
   * Create a new AbstractRefreshableApplicationContext with no parent.
   */
  public AbstractRefreshableApplicationContext() {
  }

  /**
   * Create a new AbstractRefreshableApplicationContext with the given parent context.
   * @param parent the parent context
   */
  public AbstractRefreshableApplicationContext(ApplicationContext parent) {
    super(parent);
  }


  /**
   * 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;
  }

  /**
   * 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;
  }


  /**
   * 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 {
    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);
    }
  }

  @Override
  protected void cancelRefresh(BeansException ex) {
    synchronized (this.beanFactoryMonitor) {
      if (this.beanFactory != null)
        this.beanFactory.setSerializationId(null);
    }
    super.cancelRefresh(ex);
  }

  @Override
  protected final void closeBeanFactory() {
    synchronized (this.beanFactoryMonitor) {
      this.beanFactory.setSerializationId(null);
      this.beanFactory = null;
    }
  }

  /**
   * Determine whether this context currently holds a bean factory,
   * i.e. has been refreshed at least once and not been closed yet.
   */
  protected final boolean hasBeanFactory() {
    synchronized (this.beanFactoryMonitor) {
      return (this.beanFactory != null);
    }
  }

  @Override
  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;
    }
  }


  /**
   * 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());
  }

  /**
   * 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) {
    if (this.allowBeanDefinitionOverriding != null) {
      beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }
    if (this.allowCircularReferences != null) {
      beanFactory.setAllowCircularReferences(this.allowCircularReferences);
    }
    beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
  }

  /**
   * 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;

}
TOP

Related Classes of org.springframework.context.support.AbstractRefreshableApplicationContext

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.