Save This Page
Home » spring-framework-2.5.5-with-dependencies » org.springframework » context » support » [javadoc | source]
    1   /*
    2    * Copyright 2002-2008 the original author or authors.
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *      http://www.apache.org/licenses/LICENSE-2.0
    9    *
   10    * Unless required by applicable law or agreed to in writing, software
   11    * distributed under the License is distributed on an "AS IS" BASIS,
   12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13    * See the License for the specific language governing permissions and
   14    * limitations under the License.
   15    */
   16   
   17   package org.springframework.context.support;
   18   
   19   import java.io.IOException;
   20   import java.util.ArrayList;
   21   import java.util.Collection;
   22   import java.util.Collections;
   23   import java.util.Date;
   24   import java.util.Iterator;
   25   import java.util.LinkedHashMap;
   26   import java.util.LinkedHashSet;
   27   import java.util.List;
   28   import java.util.Locale;
   29   import java.util.Map;
   30   
   31   import org.apache.commons.logging.Log;
   32   import org.apache.commons.logging.LogFactory;
   33   
   34   import org.springframework.beans.BeanUtils;
   35   import org.springframework.beans.BeansException;
   36   import org.springframework.beans.factory.BeanFactory;
   37   import org.springframework.beans.factory.BeanFactoryAware;
   38   import org.springframework.beans.factory.DisposableBean;
   39   import org.springframework.beans.factory.NoSuchBeanDefinitionException;
   40   import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
   41   import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
   42   import org.springframework.beans.factory.config.BeanPostProcessor;
   43   import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
   44   import org.springframework.beans.support.ResourceEditorRegistrar;
   45   import org.springframework.context.ApplicationContext;
   46   import org.springframework.context.ApplicationContextAware;
   47   import org.springframework.context.ApplicationEvent;
   48   import org.springframework.context.ApplicationEventPublisher;
   49   import org.springframework.context.ApplicationEventPublisherAware;
   50   import org.springframework.context.ApplicationListener;
   51   import org.springframework.context.ConfigurableApplicationContext;
   52   import org.springframework.context.HierarchicalMessageSource;
   53   import org.springframework.context.Lifecycle;
   54   import org.springframework.context.MessageSource;
   55   import org.springframework.context.MessageSourceAware;
   56   import org.springframework.context.MessageSourceResolvable;
   57   import org.springframework.context.NoSuchMessageException;
   58   import org.springframework.context.ResourceLoaderAware;
   59   import org.springframework.context.event.ApplicationEventMulticaster;
   60   import org.springframework.context.event.ContextClosedEvent;
   61   import org.springframework.context.event.ContextRefreshedEvent;
   62   import org.springframework.context.event.ContextStartedEvent;
   63   import org.springframework.context.event.ContextStoppedEvent;
   64   import org.springframework.context.event.SimpleApplicationEventMulticaster;
   65   import org.springframework.core.JdkVersion;
   66   import org.springframework.core.OrderComparator;
   67   import org.springframework.core.Ordered;
   68   import org.springframework.core.PriorityOrdered;
   69   import org.springframework.core.io.DefaultResourceLoader;
   70   import org.springframework.core.io.Resource;
   71   import org.springframework.core.io.ResourceLoader;
   72   import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
   73   import org.springframework.core.io.support.ResourcePatternResolver;
   74   import org.springframework.util.Assert;
   75   import org.springframework.util.ClassUtils;
   76   import org.springframework.util.ObjectUtils;
   77   
   78   /**
   79    * Abstract implementation of the {@link org.springframework.context.ApplicationContext}
   80    * interface. Doesn't mandate the type of storage used for configuration; simply
   81    * implements common context functionality. Uses the Template Method design pattern,
   82    * requiring concrete subclasses to implement abstract methods.
   83    *
   84    * <p>In contrast to a plain BeanFactory, an ApplicationContext is supposed
   85    * to detect special beans defined in its internal bean factory:
   86    * Therefore, this class automatically registers
   87    * {@link org.springframework.beans.factory.config.BeanFactoryPostProcessor BeanFactoryPostProcessors},
   88    * {@link org.springframework.beans.factory.config.BeanPostProcessor BeanPostProcessors}
   89    * and {@link org.springframework.context.ApplicationListener ApplicationListeners}
   90    * which are defined as beans in the context.
   91    *
   92    * <p>A {@link org.springframework.context.MessageSource} may also be supplied
   93    * as a bean in the context, with the name "messageSource"; otherwise, message
   94    * resolution is delegated to the parent context. Furthermore, a multicaster
   95    * for application events can be supplied as "applicationEventMulticaster" bean
   96    * of type {@link org.springframework.context.event.ApplicationEventMulticaster}
   97    * in the context; otherwise, a default multicaster of type
   98    * {@link org.springframework.context.event.SimpleApplicationEventMulticaster} will be used.
   99    *
  100    * <p>Implements resource loading through extending
  101    * {@link org.springframework.core.io.DefaultResourceLoader}.
  102    * Consequently treats non-URL resource paths as class path resources
  103    * (supporting full class path resource names that include the package path,
  104    * e.g. "mypackage/myresource.dat"), unless the {@link #getResourceByPath}
  105    * method is overwritten in a subclass.
  106    *
  107    * @author Rod Johnson
  108    * @author Juergen Hoeller
  109    * @author Mark Fisher
  110    * @since January 21, 2001
  111    * @see #refreshBeanFactory
  112    * @see #getBeanFactory
  113    * @see org.springframework.beans.factory.config.BeanFactoryPostProcessor
  114    * @see org.springframework.beans.factory.config.BeanPostProcessor
  115    * @see org.springframework.context.event.ApplicationEventMulticaster
  116    * @see org.springframework.context.ApplicationListener
  117    * @see org.springframework.context.MessageSource
  118    */
  119   public abstract class AbstractApplicationContext extends DefaultResourceLoader
  120   		implements ConfigurableApplicationContext, DisposableBean {
  121   
  122   	/**
  123   	 * Name of the MessageSource bean in the factory.
  124   	 * If none is supplied, message resolution is delegated to the parent.
  125   	 * @see MessageSource
  126   	 */
  127   	public static final String MESSAGE_SOURCE_BEAN_NAME = "messageSource";
  128   
  129   	/**
  130   	 * Name of the ApplicationEventMulticaster bean in the factory.
  131   	 * If none is supplied, a default SimpleApplicationEventMulticaster is used.
  132   	 * @see org.springframework.context.event.ApplicationEventMulticaster
  133   	 * @see org.springframework.context.event.SimpleApplicationEventMulticaster
  134   	 */
  135   	public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
  136   
  137   
  138   	static {
  139   		// Eagerly load the ContextClosedEvent class to avoid weird classloader issues
  140   		// on application shutdown in WebLogic 8.1. (Reported by Dustin Woods.)
  141   		ContextClosedEvent.class.getName();
  142   	}
  143   
  144   
  145   	/** Logger used by this class. Available to subclasses. */
  146   	protected final Log logger = LogFactory.getLog(getClass());
  147   
  148   	/** Unique id for this context, if any */
  149   	private String id = ObjectUtils.identityToString(this);
  150   
  151   	/** Parent context */
  152   	private ApplicationContext parent;
  153   
  154   	/** BeanFactoryPostProcessors to apply on refresh */
  155   	private final List beanFactoryPostProcessors = new ArrayList();
  156   
  157   	/** Display name */
  158   	private String displayName;
  159   
  160   	/** System time in milliseconds when this context started */
  161   	private long startupDate;
  162   
  163   	/** Flag that indicates whether this context is currently active */
  164   	private boolean active = false;
  165   
  166   	/** Synchronization monitor for the "active" flag */
  167   	private final Object activeMonitor = new Object();
  168   
  169   	/** Synchronization monitor for the "refresh" and "destroy" */
  170   	private final Object startupShutdownMonitor = new Object();
  171   
  172   	/** Reference to the JVM shutdown hook, if registered */
  173   	private Thread shutdownHook;
  174   
  175   	/** ResourcePatternResolver used by this context */
  176   	private ResourcePatternResolver resourcePatternResolver;
  177   
  178   	/** MessageSource we delegate our implementation of this interface to */
  179   	private MessageSource messageSource;
  180   
  181   	/** Helper class used in event publishing */
  182   	private ApplicationEventMulticaster applicationEventMulticaster;
  183   
  184   	/** Statically specified listeners */
  185   	private List applicationListeners = new ArrayList();
  186   
  187   
  188   	/**
  189   	 * Create a new AbstractApplicationContext with no parent.
  190   	 */
  191   	public AbstractApplicationContext() {
  192   		this(null);
  193   	}
  194   
  195   	/**
  196   	 * Create a new AbstractApplicationContext with the given parent context.
  197   	 * @param parent the parent context
  198   	 */
  199   	public AbstractApplicationContext(ApplicationContext parent) {
  200   		this.parent = parent;
  201   		this.resourcePatternResolver = getResourcePatternResolver();
  202   	}
  203   
  204   
  205   	//---------------------------------------------------------------------
  206   	// Implementation of ApplicationContext interface
  207   	//---------------------------------------------------------------------
  208   
  209   	/**
  210   	 * Set the unique id of this application context.
  211   	 * <p>Default is the object id of the context instance, or the name
  212   	 * of the context bean if the context is itself defined as a bean.
  213   	 * @param id the unique id of the context
  214   	 */
  215   	public void setId(String id) {
  216   		this.id = id;
  217   	}
  218   
  219   	public String getId() {
  220   		return this.id;
  221   	}
  222   
  223   	/**
  224   	 * Return the parent context, or <code>null</code> if there is no parent
  225   	 * (that is, this context is the root of the context hierarchy).
  226   	 */
  227   	public ApplicationContext getParent() {
  228   		return this.parent;
  229   	}
  230   
  231   	/**
  232   	 * Return this context's internal bean factory as AutowireCapableBeanFactory,
  233   	 * if already available.
  234   	 * @see #getBeanFactory()
  235   	 */
  236   	public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException {
  237   		return getBeanFactory();
  238   	}
  239   
  240   	/**
  241   	 * Set a friendly name for this context.
  242   	 * Typically done during initialization of concrete context implementations.
  243   	 */
  244   	public void setDisplayName(String displayName) {
  245   		this.displayName = displayName;
  246   	}
  247   
  248   	/**
  249   	 * Return a friendly name for this context.
  250   	 */
  251   	public String getDisplayName() {
  252   		return (this.displayName != null ? this.displayName : getId());
  253   	}
  254   
  255   	/**
  256   	 * Return the timestamp (ms) when this context was first loaded.
  257   	 */
  258   	public long getStartupDate() {
  259   		return this.startupDate;
  260   	}
  261   
  262   	/**
  263   	 * Publish the given event to all listeners.
  264   	 * <p>Note: Listeners get initialized after the MessageSource, to be able
  265   	 * to access it within listener implementations. Thus, MessageSource
  266   	 * implementations cannot publish events.
  267   	 * @param event the event to publish (may be application-specific or a
  268   	 * standard framework event)
  269   	 */
  270   	public void publishEvent(ApplicationEvent event) {
  271   		Assert.notNull(event, "Event must not be null");
  272   		if (logger.isDebugEnabled()) {
  273   			logger.debug("Publishing event in context [" + getId() + "]: " + event);
  274   		}
  275   		getApplicationEventMulticaster().multicastEvent(event);
  276   		if (this.parent != null) {
  277   			this.parent.publishEvent(event);
  278   		}
  279   	}
  280   
  281   	/**
  282   	 * Return the internal MessageSource used by the context.
  283   	 * @return the internal MessageSource (never <code>null</code>)
  284   	 * @throws IllegalStateException if the context has not been initialized yet
  285   	 */
  286   	private ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException {
  287   		if (this.applicationEventMulticaster == null) {
  288   			throw new IllegalStateException("ApplicationEventMulticaster not initialized - " +
  289   					"call 'refresh' before multicasting events via the context: " + this);
  290   		}
  291   		return this.applicationEventMulticaster;
  292   	}
  293   
  294   	/**
  295   	 * Return the ResourcePatternResolver to use for resolving location patterns
  296   	 * into Resource instances. Default is a
  297   	 * {@link org.springframework.core.io.support.PathMatchingResourcePatternResolver},
  298   	 * supporting Ant-style location patterns.
  299   	 * <p>Can be overridden in subclasses, for extended resolution strategies,
  300   	 * for example in a web environment.
  301   	 * <p><b>Do not call this when needing to resolve a location pattern.</b>
  302   	 * Call the context's <code>getResources</code> method instead, which
  303   	 * will delegate to the ResourcePatternResolver.
  304   	 * @return the ResourcePatternResolver for this context
  305   	 * @see #getResources
  306   	 * @see org.springframework.core.io.support.PathMatchingResourcePatternResolver
  307   	 */
  308   	protected ResourcePatternResolver getResourcePatternResolver() {
  309   		return new PathMatchingResourcePatternResolver(this);
  310   	}
  311   
  312   
  313   	//---------------------------------------------------------------------
  314   	// Implementation of ConfigurableApplicationContext interface
  315   	//---------------------------------------------------------------------
  316   
  317   	public void setParent(ApplicationContext parent) {
  318   		this.parent = parent;
  319   	}
  320   
  321   	public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor beanFactoryPostProcessor) {
  322   		this.beanFactoryPostProcessors.add(beanFactoryPostProcessor);
  323   	}
  324   
  325   	/**
  326   	 * Return the list of BeanFactoryPostProcessors that will get applied
  327   	 * to the internal BeanFactory.
  328   	 * @see org.springframework.beans.factory.config.BeanFactoryPostProcessor
  329   	 */
  330   	public List getBeanFactoryPostProcessors() {
  331   		return this.beanFactoryPostProcessors;
  332   	}
  333   
  334   	public void addApplicationListener(ApplicationListener listener) {
  335   		this.applicationListeners.add(listener);
  336   	}
  337   
  338   	/**
  339   	 * Return the list of statically specified ApplicationListeners.
  340   	 * @see org.springframework.context.ApplicationListener
  341   	 */
  342   	public List getApplicationListeners() {
  343   		return this.applicationListeners;
  344   	}
  345   
  346   
  347   	public void refresh() throws BeansException, IllegalStateException {
  348   		synchronized (this.startupShutdownMonitor) {
  349   			// Prepare this context for refreshing.
  350   			prepareRefresh();
  351   
  352   			// Tell the subclass to refresh the internal bean factory.
  353   			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
  354   
  355   			// Prepare the bean factory for use in this context.
  356   			prepareBeanFactory(beanFactory);
  357   
  358   			try {
  359   				// Allows post-processing of the bean factory in context subclasses.
  360   				postProcessBeanFactory(beanFactory);
  361   
  362   				// Invoke factory processors registered as beans in the context.
  363   				invokeBeanFactoryPostProcessors(beanFactory);
  364   
  365   				// Register bean processors that intercept bean creation.
  366   				registerBeanPostProcessors(beanFactory);
  367   
  368   				// Initialize message source for this context.
  369   				initMessageSource();
  370   
  371   				// Initialize event multicaster for this context.
  372   				initApplicationEventMulticaster();
  373   
  374   				// Initialize other special beans in specific context subclasses.
  375   				onRefresh();
  376   
  377   				// Check for listener beans and register them.
  378   				registerListeners();
  379   
  380   				// Instantiate all remaining (non-lazy-init) singletons.
  381   				finishBeanFactoryInitialization(beanFactory);
  382   
  383   				// Last step: publish corresponding event.
  384   				finishRefresh();
  385   			}
  386   
  387   			catch (BeansException ex) {
  388   				// Destroy already created singletons to avoid dangling resources.
  389   				beanFactory.destroySingletons();
  390   
  391   				// Reset 'active' flag.
  392   				cancelRefresh(ex);
  393   
  394   				// Propagate exception to caller.
  395   				throw ex;
  396   			}
  397   		}
  398   	}
  399   
  400   	/**
  401   	 * Prepare this context for refreshing, setting its startup date and
  402   	 * active flag.
  403   	 */
  404   	protected void prepareRefresh() {
  405   		this.startupDate = System.currentTimeMillis();
  406   
  407   		synchronized (this.activeMonitor) {
  408   			this.active = true;
  409   		}
  410   
  411   		if (logger.isInfoEnabled()) {
  412   			logger.info("Refreshing " + this);
  413   		}
  414   	}
  415   
  416   	/**
  417   	 * Tell the subclass to refresh the internal bean factory.
  418   	 * @return the fresh BeanFactory instance
  419   	 * @see #refreshBeanFactory()
  420   	 * @see #getBeanFactory()
  421   	 */
  422   	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
  423   		refreshBeanFactory();
  424   		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
  425   
  426   		if (logger.isInfoEnabled()) {
  427   			logger.info("Bean factory for application context [" + getId() + "]: " +
  428   					ObjectUtils.identityToString(beanFactory));
  429   		}
  430   		if (logger.isDebugEnabled()) {
  431   			logger.debug(beanFactory.getBeanDefinitionCount() + " beans defined in " + this);
  432   		}
  433   
  434   		return beanFactory;
  435   	}
  436   
  437   	/**
  438   	 * Configure the factory's standard context characteristics,
  439   	 * such as the context's ClassLoader and post-processors.
  440   	 * @param beanFactory the BeanFactory to configure
  441   	 */
  442   	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
  443   		// Tell the internal bean factory to use the context's class loader.
  444   		beanFactory.setBeanClassLoader(getClassLoader());
  445   
  446   		// Populate the bean factory with context-specific resource editors.
  447   		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this));
  448   
  449   		// Configure the bean factory with context callbacks.
  450   		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
  451   		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
  452   		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
  453   		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
  454   		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
  455   
  456   		// BeanFactory interface not registered as resolvable type in a plain factory.
  457   		// MessageSource registered (and found for autowiring) as a bean.
  458   		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
  459   		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
  460   		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
  461   		beanFactory.registerResolvableDependency(ApplicationContext.class, this);
  462   
  463   		// Detect a LoadTimeWeaver and prepare for weaving, if found.
  464   		if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME) && JdkVersion.isAtLeastJava15()) {
  465   			// Register the (JDK 1.5 specific) LoadTimeWeaverAwareProcessor.
  466   			try {
  467   				Class ltwapClass = ClassUtils.forName(
  468   						"org.springframework.context.weaving.LoadTimeWeaverAwareProcessor",
  469   						AbstractApplicationContext.class.getClassLoader());
  470   				BeanPostProcessor ltwap = (BeanPostProcessor) BeanUtils.instantiateClass(ltwapClass);
  471   				((BeanFactoryAware) ltwap).setBeanFactory(beanFactory);
  472   				beanFactory.addBeanPostProcessor(ltwap);
  473   			}
  474   			catch (ClassNotFoundException ex) {
  475   				throw new IllegalStateException("Spring's LoadTimeWeaverAwareProcessor class is not available");
  476   			}
  477   			// Set a temporary ClassLoader for type matching.
  478   			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
  479   		}
  480   	}
  481   
  482   	/**
  483   	 * Modify the application context's internal bean factory after its standard
  484   	 * initialization. All bean definitions will have been loaded, but no beans
  485   	 * will have been instantiated yet. This allows for registering special
  486   	 * BeanPostProcessors etc in certain ApplicationContext implementations.
  487   	 * @param beanFactory the bean factory used by the application context
  488   	 */
  489   	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
  490   	}
  491   
  492   	/**
  493   	 * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
  494   	 * respecting explicit order if given.
  495   	 * <p>Must be called before singleton instantiation.
  496   	 */
  497   	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
  498   		// Invoke factory processors registered with the context instance.
  499   		for (Iterator it = getBeanFactoryPostProcessors().iterator(); it.hasNext();) {
  500   			BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor) it.next();
  501   			factoryProcessor.postProcessBeanFactory(beanFactory);
  502   		}
  503   
  504   		// Do not initialize FactoryBeans here: We need to leave all regular beans
  505   		// uninitialized to let the bean factory post-processors apply to them!
  506   		String[] postProcessorNames =
  507   				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
  508   
  509   		// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
  510   		// Ordered, and the rest.
  511   		List priorityOrderedPostProcessors = new ArrayList();
  512   		List orderedPostProcessorNames = new ArrayList();
  513   		List nonOrderedPostProcessorNames = new ArrayList();
  514   		for (int i = 0; i < postProcessorNames.length; i++) {
  515   			if (isTypeMatch(postProcessorNames[i], PriorityOrdered.class)) {
  516   				priorityOrderedPostProcessors.add(beanFactory.getBean(postProcessorNames[i]));
  517   			}
  518   			else if (isTypeMatch(postProcessorNames[i], Ordered.class)) {
  519   				orderedPostProcessorNames.add(postProcessorNames[i]);
  520   			}
  521   			else {
  522   				nonOrderedPostProcessorNames.add(postProcessorNames[i]);
  523   			}
  524   		}
  525   
  526   		// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
  527   		Collections.sort(priorityOrderedPostProcessors, new OrderComparator());
  528   		invokeBeanFactoryPostProcessors(beanFactory, priorityOrderedPostProcessors);
  529   
  530   		// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
  531   		List orderedPostProcessors = new ArrayList();
  532   		for (Iterator it = orderedPostProcessorNames.iterator(); it.hasNext();) {
  533   			String postProcessorName = (String) it.next();
  534   			orderedPostProcessors.add(getBean(postProcessorName));
  535   		}
  536   		Collections.sort(orderedPostProcessors, new OrderComparator());
  537   		invokeBeanFactoryPostProcessors(beanFactory, orderedPostProcessors);
  538   
  539   		// Finally, invoke all other BeanFactoryPostProcessors.
  540   		List nonOrderedPostProcessors = new ArrayList();
  541   		for (Iterator it = nonOrderedPostProcessorNames.iterator(); it.hasNext();) {
  542   			String postProcessorName = (String) it.next();
  543   			nonOrderedPostProcessors.add(getBean(postProcessorName));
  544   		}
  545   		invokeBeanFactoryPostProcessors(beanFactory, nonOrderedPostProcessors);
  546   	}
  547   
  548   	/**
  549   	 * Invoke the given BeanFactoryPostProcessor beans.
  550   	 */
  551   	private void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List postProcessors) {
  552   		for (Iterator it = postProcessors.iterator(); it.hasNext();) {
  553   			BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor) it.next();
  554   			postProcessor.postProcessBeanFactory(beanFactory);
  555   		}
  556   	}
  557   
  558   	/**
  559   	 * Instantiate and invoke all registered BeanPostProcessor beans,
  560   	 * respecting explicit order if given.
  561   	 * <p>Must be called before any instantiation of application beans.
  562   	 */
  563   	protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
  564   		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
  565   
  566   		// Register BeanPostProcessorChecker that logs an info message when
  567   		// a bean is created during BeanPostProcessor instantiation, i.e. when
  568   		// a bean is not eligible for getting processed by all BeanPostProcessors.
  569   		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
  570   		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
  571   
  572   		// Separate between BeanPostProcessors that implement PriorityOrdered,
  573   		// Ordered, and the rest.
  574   		List priorityOrderedPostProcessors = new ArrayList();
  575   		List orderedPostProcessorNames = new ArrayList();
  576   		List nonOrderedPostProcessorNames = new ArrayList();
  577   		for (int i = 0; i < postProcessorNames.length; i++) {
  578   			if (isTypeMatch(postProcessorNames[i], PriorityOrdered.class)) {
  579   				priorityOrderedPostProcessors.add(beanFactory.getBean(postProcessorNames[i]));
  580   			}
  581   			else if (isTypeMatch(postProcessorNames[i], Ordered.class)) {
  582   				orderedPostProcessorNames.add(postProcessorNames[i]);
  583   			}
  584   			else {
  585   				nonOrderedPostProcessorNames.add(postProcessorNames[i]);
  586   			}
  587   		}
  588   
  589   		// First, register the BeanPostProcessors that implement PriorityOrdered.
  590   		Collections.sort(priorityOrderedPostProcessors, new OrderComparator());
  591   		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
  592   
  593   		// Next, register the BeanPostProcessors that implement Ordered.
  594   		List orderedPostProcessors = new ArrayList();
  595   		for (Iterator it = orderedPostProcessorNames.iterator(); it.hasNext();) {
  596   			String postProcessorName = (String) it.next();
  597   			orderedPostProcessors.add(getBean(postProcessorName));
  598   		}
  599   		Collections.sort(orderedPostProcessors, new OrderComparator());
  600   		registerBeanPostProcessors(beanFactory, orderedPostProcessors);
  601   
  602   		// Finally, register all other BeanPostProcessors.
  603   		List nonOrderedPostProcessors = new ArrayList();
  604   		for (Iterator it = nonOrderedPostProcessorNames.iterator(); it.hasNext();) {
  605   			String postProcessorName = (String) it.next();
  606   			nonOrderedPostProcessors.add(getBean(postProcessorName));
  607   		}
  608   		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
  609   	}
  610   
  611   	/**
  612   	 * Register the given BeanPostProcessor beans.
  613   	 */
  614   	private void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, List postProcessors) {
  615   		for (Iterator it = postProcessors.iterator(); it.hasNext();) {
  616   			BeanPostProcessor postProcessor = (BeanPostProcessor) it.next();
  617   			beanFactory.addBeanPostProcessor(postProcessor);
  618   		}
  619   	}
  620   
  621   	/**
  622   	 * Initialize the MessageSource.
  623   	 * Use parent's if none defined in this context.
  624   	 */
  625   	protected void initMessageSource() {
  626   		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
  627   		if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
  628   			this.messageSource = (MessageSource) beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
  629   			// Make MessageSource aware of parent MessageSource.
  630   			if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
  631   				HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
  632   				if (hms.getParentMessageSource() == null) {
  633   					// Only set parent context as parent MessageSource if no parent MessageSource
  634   					// registered already.
  635   					hms.setParentMessageSource(getInternalParentMessageSource());
  636   				}
  637   			}
  638   			if (logger.isDebugEnabled()) {
  639   				logger.debug("Using MessageSource [" + this.messageSource + "]");
  640   			}
  641   		}
  642   		else {
  643   			// Use empty MessageSource to be able to accept getMessage calls.
  644   			DelegatingMessageSource dms = new DelegatingMessageSource();
  645   			dms.setParentMessageSource(getInternalParentMessageSource());
  646   			this.messageSource = dms;
  647   			beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
  648   			if (logger.isDebugEnabled()) {
  649   				logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
  650   						"': using default [" + this.messageSource + "]");
  651   			}
  652   		}
  653   	}
  654   
  655   	/**
  656   	 * Initialize the ApplicationEventMulticaster.
  657   	 * Uses SimpleApplicationEventMulticaster if none defined in the context.
  658   	 * @see org.springframework.context.event.SimpleApplicationEventMulticaster
  659   	 */
  660   	protected void initApplicationEventMulticaster() {
  661   		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
  662   		if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
  663   			this.applicationEventMulticaster = (ApplicationEventMulticaster)
  664   					beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
  665   			if (logger.isDebugEnabled()) {
  666   				logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
  667   			}
  668   		}
  669   		else {
  670   			this.applicationEventMulticaster = new SimpleApplicationEventMulticaster();
  671   			beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
  672   			if (logger.isDebugEnabled()) {
  673   				logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
  674   						APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
  675   						"': using default [" + this.applicationEventMulticaster + "]");
  676   			}
  677   		}
  678   	}
  679   
  680   	/**
  681   	 * Template method which can be overridden to add context-specific refresh work.
  682   	 * Called on initialization of special beans, before instantiation of singletons.
  683   	 * <p>This implementation is empty.
  684   	 * @throws BeansException in case of errors
  685   	 * @see #refresh()
  686   	 */
  687   	protected void onRefresh() throws BeansException {
  688   		// For subclasses: do nothing by default.
  689   	}
  690   
  691   	/**
  692   	 * Add beans that implement ApplicationListener as listeners.
  693   	 * Doesn't affect other listeners, which can be added without being beans.
  694   	 */
  695   	protected void registerListeners() {
  696   		// Register statically specified listeners first.
  697   		for (Iterator it = getApplicationListeners().iterator(); it.hasNext();) {
  698   			addListener((ApplicationListener) it.next());
  699   		}
  700   		// Do not initialize FactoryBeans here: We need to leave all regular beans
  701   		// uninitialized to let post-processors apply to them!
  702   		Collection listenerBeans = getBeansOfType(ApplicationListener.class, true, false).values();
  703   		for (Iterator it = listenerBeans.iterator(); it.hasNext();) {
  704   			addListener((ApplicationListener) it.next());
  705   		}
  706   	}
  707   
  708   	/**
  709   	 * Subclasses can invoke this method to register a listener.
  710   	 * Any beans in the context that are listeners are automatically added.
  711   	 * @param listener the listener to register
  712   	 */
  713   	protected void addListener(ApplicationListener listener) {
  714   		getApplicationEventMulticaster().addApplicationListener(listener);
  715   	}
  716   
  717   	/**
  718   	 * Finish the initialization of this context's bean factory,
  719   	 * initializing all remaining singleton beans.
  720   	 */
  721   	protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
  722   		// Stop using the temporary ClassLoader for type matching.
  723   		beanFactory.setTempClassLoader(null);
  724   
  725   		// Allow for caching all bean definition metadata, not expecting further changes.
  726   		beanFactory.freezeConfiguration();
  727   
  728   		// Instantiate all remaining (non-lazy-init) singletons.
  729   		beanFactory.preInstantiateSingletons();
  730   	}
  731   
  732   	/**
  733   	 * Finish the refresh of this context, publishing the
  734   	 * {@link org.springframework.context.event.ContextRefreshedEvent}.
  735   	 */
  736   	protected void finishRefresh() {
  737   		publishEvent(new ContextRefreshedEvent(this));
  738   	}
  739   
  740   	/**
  741   	 * Cancel this context's refresh attempt, resetting the <code>active</code> flag
  742   	 * after an exception got thrown.
  743   	 * @param ex the exception that led to the cancellation
  744   	 */
  745   	protected void cancelRefresh(BeansException ex) {
  746   		synchronized (this.activeMonitor) {
  747   			this.active = false;
  748   		}
  749   	}
  750   
  751   
  752   	/**
  753   	 * Register a shutdown hook with the JVM runtime, closing this context
  754   	 * on JVM shutdown unless it has already been closed at that time.
  755   	 * <p>Delegates to <code>doClose()</code> for the actual closing procedure.
  756   	 * @see java.lang.Runtime#addShutdownHook
  757   	 * @see #close()
  758   	 * @see #doClose()
  759   	 */
  760   	public void registerShutdownHook() {
  761   		if (this.shutdownHook == null) {
  762   			// No shutdown hook registered yet.
  763   			this.shutdownHook = new Thread() {
  764   				public void run() {
  765   					doClose();
  766   				}
  767   			};
  768   			Runtime.getRuntime().addShutdownHook(this.shutdownHook);
  769   		}
  770   	}
  771   
  772   	/**
  773   	 * DisposableBean callback for destruction of this instance.
  774   	 * Only called when the ApplicationContext itself is running
  775   	 * as a bean in another BeanFactory or ApplicationContext,
  776   	 * which is rather unusual.
  777   	 * <p>The <code>close</code> method is the native way to
  778   	 * shut down an ApplicationContext.
  779   	 * @see #close()
  780   	 * @see org.springframework.beans.factory.access.SingletonBeanFactoryLocator
  781   	 */
  782   	public void destroy() {
  783   		close();
  784   	}
  785   
  786   	/**
  787   	 * Close this application context, destroying all beans in its bean factory.
  788   	 * <p>Delegates to <code>doClose()</code> for the actual closing procedure.
  789   	 * Also removes a JVM shutdown hook, if registered, as it's not needed anymore.
  790   	 * @see #doClose()
  791   	 * @see #registerShutdownHook()
  792   	 */
  793   	public void close() {
  794   		synchronized (this.startupShutdownMonitor) {
  795   			doClose();
  796   			// If we registered a JVM shutdown hook, we don't need it anymore now:
  797   			// We've already explicitly closed the context.
  798   			if (this.shutdownHook != null) {
  799   				Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
  800   			}
  801   		}
  802   	}
  803   
  804   	/**
  805   	 * Actually performs context closing: publishes a ContextClosedEvent and
  806   	 * destroys the singletons in the bean factory of this application context.
  807   	 * <p>Called by both <code>close()</code> and a JVM shutdown hook, if any.
  808   	 * @see org.springframework.context.event.ContextClosedEvent
  809   	 * @see org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons()
  810   	 * @see #close()
  811   	 * @see #registerShutdownHook()
  812   	 */
  813   	protected void doClose() {
  814   		if (isActive()) {
  815   			if (logger.isInfoEnabled()) {
  816   				logger.info("Closing " + this);
  817   			}
  818   			try {
  819   				// Publish shutdown event.
  820   				publishEvent(new ContextClosedEvent(this));
  821   			}
  822   			catch (Throwable ex) {
  823   				logger.error("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
  824   			}
  825   			// Stop all Lifecycle beans, to avoid delays during individual destruction.
  826   			Map lifecycleBeans = getLifecycleBeans();
  827   			for (Iterator it = new LinkedHashSet(lifecycleBeans.keySet()).iterator(); it.hasNext();) {
  828   				String beanName = (String) it.next();
  829   				doStop(lifecycleBeans, beanName);
  830   			}
  831   			// Destroy all cached singletons in the context's BeanFactory.
  832   			destroyBeans();
  833   			// Close the state of this context itself.
  834   			closeBeanFactory();
  835   			onClose();
  836   			synchronized (this.activeMonitor) {
  837   				this.active = false;
  838   			}
  839   		}
  840   	}
  841   
  842   	/**
  843   	 * Template method for destroying all beans that this context manages.
  844   	 * The default implementation destroy all cached singletons in this context,
  845   	 * invoking <code>DisposableBean.destroy()</code> and/or the specified
  846   	 * "destroy-method".
  847   	 * <p>Can be overridden to add context-specific bean destruction steps
  848   	 * right before or right after standard singleton destruction,
  849   	 * while the context's BeanFactory is still active.
  850   	 * @see #getBeanFactory()
  851   	 * @see org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons()
  852   	 */
  853   	protected void destroyBeans() {
  854   		getBeanFactory().destroySingletons();
  855   	}
  856   
  857   	/**
  858   	 * Template method which can be overridden to add context-specific shutdown work.
  859   	 * The default implementation is empty.
  860   	 * <p>Called at the end of {@link #doClose}'s shutdown procedure, after
  861   	 * this context's BeanFactory has been closed. If custom shutdown logic
  862   	 * needs to execute while the BeanFactory is still active, override
  863   	 * the {@link #destroyBeans()} method instead.
  864   	 */
  865   	protected void onClose() {
  866   		// For subclasses: do nothing by default.
  867   	}
  868   
  869   	public boolean isActive() {
  870   		synchronized (this.activeMonitor) {
  871   			return this.active;
  872   		}
  873   	}
  874   
  875   
  876   	//---------------------------------------------------------------------
  877   	// Implementation of BeanFactory interface
  878   	//---------------------------------------------------------------------
  879   
  880   	public Object getBean(String name) throws BeansException {
  881   		return getBeanFactory().getBean(name);
  882   	}
  883   
  884   	public Object getBean(String name, Class requiredType) throws BeansException {
  885   		return getBeanFactory().getBean(name, requiredType);
  886   	}
  887   
  888   	public Object getBean(String name, Object[] args) throws BeansException {
  889   		return getBeanFactory().getBean(name, args);
  890   	}
  891   
  892   	public boolean containsBean(String name) {
  893   		return getBeanFactory().containsBean(name);
  894   	}
  895   
  896   	public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
  897   		return getBeanFactory().isSingleton(name);
  898   	}
  899   
  900   	public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
  901   		return getBeanFactory().isPrototype(name);
  902   	}
  903   
  904   	public boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException {
  905   		return getBeanFactory().isTypeMatch(name, targetType);
  906   	}
  907   
  908   	public Class getType(String name) throws NoSuchBeanDefinitionException {
  909   		return getBeanFactory().getType(name);
  910   	}
  911   
  912   	public String[] getAliases(String name) {
  913   		return getBeanFactory().getAliases(name);
  914   	}
  915   
  916   
  917   	//---------------------------------------------------------------------
  918   	// Implementation of ListableBeanFactory interface
  919   	//---------------------------------------------------------------------
  920   
  921   	public boolean containsBeanDefinition(String name) {
  922   		return getBeanFactory().containsBeanDefinition(name);
  923   	}
  924   
  925   	public int getBeanDefinitionCount() {
  926   		return getBeanFactory().getBeanDefinitionCount();
  927   	}
  928   
  929   	public String[] getBeanDefinitionNames() {
  930   		return getBeanFactory().getBeanDefinitionNames();
  931   	}
  932   
  933   	public String[] getBeanNamesForType(Class type) {
  934   		return getBeanFactory().getBeanNamesForType(type);
  935   	}
  936   
  937   	public String[] getBeanNamesForType(Class type, boolean includePrototypes, boolean allowEagerInit) {
  938   		return getBeanFactory().getBeanNamesForType(type, includePrototypes, allowEagerInit);
  939   	}
  940   
  941   	public Map getBeansOfType(Class type) throws BeansException {
  942   		return getBeanFactory().getBeansOfType(type);
  943   	}
  944   
  945   	public Map getBeansOfType(Class type, boolean includePrototypes, boolean allowEagerInit)
  946   			throws BeansException {
  947   
  948   		return getBeanFactory().getBeansOfType(type, includePrototypes, allowEagerInit);
  949   	}
  950   
  951   
  952   	//---------------------------------------------------------------------
  953   	// Implementation of HierarchicalBeanFactory interface
  954   	//---------------------------------------------------------------------
  955   
  956   	public BeanFactory getParentBeanFactory() {
  957   		return getParent();
  958   	}
  959   
  960   	public boolean containsLocalBean(String name) {
  961   		return getBeanFactory().containsLocalBean(name);
  962   	}
  963   
  964   	/**
  965   	 * Return the internal bean factory of the parent context if it implements
  966   	 * ConfigurableApplicationContext; else, return the parent context itself.
  967   	 * @see org.springframework.context.ConfigurableApplicationContext#getBeanFactory
  968   	 */
  969   	protected BeanFactory getInternalParentBeanFactory() {
  970   		return (getParent() instanceof ConfigurableApplicationContext) ?
  971   				((ConfigurableApplicationContext) getParent()).getBeanFactory() : (BeanFactory) getParent();
  972   	}
  973   
  974   
  975   	//---------------------------------------------------------------------
  976   	// Implementation of MessageSource interface
  977   	//---------------------------------------------------------------------
  978   
  979   	public String getMessage(String code, Object args[], String defaultMessage, Locale locale) {
  980   		return getMessageSource().getMessage(code, args, defaultMessage, locale);
  981   	}
  982   
  983   	public String getMessage(String code, Object args[], Locale locale) throws NoSuchMessageException {
  984   		return getMessageSource().getMessage(code, args, locale);
  985   	}
  986   
  987   	public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException {
  988   		return getMessageSource().getMessage(resolvable, locale);
  989   	}
  990   
  991   	/**
  992   	 * Return the internal MessageSource used by the context.
  993   	 * @return the internal MessageSource (never <code>null</code>)
  994   	 * @throws IllegalStateException if the context has not been initialized yet
  995   	 */
  996   	private MessageSource getMessageSource() throws IllegalStateException {
  997   		if (this.messageSource == null) {
  998   			throw new IllegalStateException("MessageSource not initialized - " +
  999   					"call 'refresh' before accessing messages via the context: " + this);
 1000   		}
 1001   		return this.messageSource;
 1002   	}
 1003   
 1004   	/**
 1005   	 * Return the internal message source of the parent context if it is an
 1006   	 * AbstractApplicationContext too; else, return the parent context itself.
 1007   	 */
 1008   	protected MessageSource getInternalParentMessageSource() {
 1009   		return (getParent() instanceof AbstractApplicationContext) ?
 1010   		    ((AbstractApplicationContext) getParent()).messageSource : getParent();
 1011   	}
 1012   
 1013   
 1014   	//---------------------------------------------------------------------
 1015   	// Implementation of ResourcePatternResolver interface
 1016   	//---------------------------------------------------------------------
 1017   
 1018   	public Resource[] getResources(String locationPattern) throws IOException {
 1019   		return this.resourcePatternResolver.getResources(locationPattern);
 1020   	}
 1021   
 1022   
 1023   	//---------------------------------------------------------------------
 1024   	// Implementation of Lifecycle interface
 1025   	//---------------------------------------------------------------------
 1026   
 1027   	public void start() {
 1028   		Map lifecycleBeans = getLifecycleBeans();
 1029   		for (Iterator it = new LinkedHashSet(lifecycleBeans.keySet()).iterator(); it.hasNext();) {
 1030   			String beanName = (String) it.next();
 1031   			doStart(lifecycleBeans, beanName);
 1032   		}
 1033   		publishEvent(new ContextStartedEvent(this));
 1034   	}
 1035   
 1036   	public void stop() {
 1037   		Map lifecycleBeans = getLifecycleBeans();
 1038   		for (Iterator it = new LinkedHashSet(lifecycleBeans.keySet()).iterator(); it.hasNext();) {
 1039   			String beanName = (String) it.next();
 1040   			doStop(lifecycleBeans, beanName);
 1041   		}
 1042   		publishEvent(new ContextStoppedEvent(this));
 1043   	}
 1044   
 1045   	public boolean isRunning() {
 1046   		Iterator it = getLifecycleBeans().values().iterator();
 1047   		while (it.hasNext()) {
 1048   			Lifecycle lifecycle = (Lifecycle) it.next();
 1049   			if (!lifecycle.isRunning()) {
 1050   				return false;
 1051   			}
 1052   		}
 1053   		return true;
 1054   	}
 1055   
 1056   	/**
 1057   	 * Return a Map of all singleton beans that implement the
 1058   	 * Lifecycle interface in this context.
 1059   	 * @return Map of Lifecycle beans with bean name as key
 1060   	 */
 1061   	private Map getLifecycleBeans() {
 1062   		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
 1063   		String[] beanNames = beanFactory.getSingletonNames();
 1064   		Map beans = new LinkedHashMap();
 1065   		for (int i = 0; i < beanNames.length; i++) {
 1066   			Object bean = beanFactory.getSingleton(beanNames[i]);
 1067   			if (bean instanceof Lifecycle) {
 1068   				beans.put(beanNames[i], bean);
 1069   			}
 1070   		}
 1071   		return beans;
 1072   	}
 1073   
 1074   	/**
 1075   	 * Start the specified bean as part of the given set of Lifecycle beans,
 1076   	 * making sure that any beans that it depends on are started first.
 1077   	 * @param lifecycleBeans Map with bean name as key and Lifecycle instance as value
 1078   	 * @param beanName the name of the bean to start
 1079   	 */
 1080   	private void doStart(Map lifecycleBeans, String beanName) {
 1081   		Lifecycle bean = (Lifecycle) lifecycleBeans.get(beanName);
 1082   		if (bean != null) {
 1083   			String[] dependenciesForBean = getBeanFactory().getDependenciesForBean(beanName);
 1084   			for (int i = 0; i < dependenciesForBean.length; i++) {
 1085   				doStart(lifecycleBeans, dependenciesForBean[i]);
 1086   			}
 1087   			if (!bean.isRunning()) {
 1088   				bean.start();
 1089   			}
 1090   			lifecycleBeans.remove(beanName);
 1091   		}
 1092   	}
 1093   
 1094   	/**
 1095   	 * Stop the specified bean as part of the given set of Lifecycle beans,
 1096   	 * making sure that any beans that depends on it are stopped first.
 1097   	 * @param lifecycleBeans Map with bean name as key and Lifecycle instance as value
 1098   	 * @param beanName the name of the bean to stop
 1099   	 */
 1100   	private void doStop(Map lifecycleBeans, String beanName) {
 1101   		Lifecycle bean = (Lifecycle) lifecycleBeans.get(beanName);
 1102   		if (bean != null) {
 1103   			String[] dependentBeans = getBeanFactory().getDependentBeans(beanName);
 1104   			for (int i = 0; i < dependentBeans.length; i++) {
 1105   				doStop(lifecycleBeans, dependentBeans[i]);
 1106   			}
 1107   			if (bean.isRunning()) {
 1108   				bean.stop();
 1109   			}
 1110   			lifecycleBeans.remove(beanName);
 1111   		}
 1112   	}
 1113   
 1114   
 1115   	//---------------------------------------------------------------------
 1116   	// Abstract methods that must be implemented by subclasses
 1117   	//---------------------------------------------------------------------
 1118   
 1119   	/**
 1120   	 * Subclasses must implement this method to perform the actual configuration load.
 1121   	 * The method is invoked by {@link #refresh()} before any other initialization work.
 1122   	 * <p>A subclass will either create a new bean factory and hold a reference to it,
 1123   	 * or return a single BeanFactory instance that it holds. In the latter case, it will
 1124   	 * usually throw an IllegalStateException if refreshing the context more than once.
 1125   	 * @throws BeansException if initialization of the bean factory failed
 1126   	 * @throws IllegalStateException if already initialized and multiple refresh
 1127   	 * attempts are not supported
 1128   	 */
 1129   	protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
 1130   
 1131   	/**
 1132   	 * Subclasses must implement this method to release their internal bean factory.
 1133   	 * This method gets invoked by {@link #close()} after all other shutdown work.
 1134   	 * <p>Should never throw an exception but rather log shutdown failures.
 1135   	 */
 1136   	protected abstract void closeBeanFactory();
 1137   
 1138   	/**
 1139   	 * Subclasses must return their internal bean factory here. They should implement the
 1140   	 * lookup efficiently, so that it can be called repeatedly without a performance penalty.
 1141   	 * <p>Note: Subclasses should check whether the context is still active before
 1142   	 * returning the internal bean factory. The internal factory should generally be
 1143   	 * considered unavailable once the context has been closed.
 1144   	 * @return this application context's internal bean factory (never <code>null</code>)
 1145   	 * @throws IllegalStateException if the context does not hold an internal bean factory yet
 1146   	 * (usually if {@link #refresh()} has never been called) or if the context has been
 1147   	 * closed already
 1148   	 * @see #refreshBeanFactory()
 1149   	 * @see #closeBeanFactory()
 1150   	 */
 1151   	public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
 1152   
 1153   
 1154   	/**
 1155   	 * Return information about this context.
 1156   	 */
 1157   	public String toString() {
 1158   		StringBuffer sb = new StringBuffer(getId());
 1159   		sb.append(": display name [").append(getDisplayName());
 1160   		sb.append("]; startup date [").append(new Date(getStartupDate()));
 1161   		sb.append("]; ");
 1162   		ApplicationContext parent = getParent();
 1163   		if (parent == null) {
 1164   			sb.append("root of context hierarchy");
 1165   		}
 1166   		else {
 1167   			sb.append("parent: ").append(parent.getId());
 1168   		}
 1169   		return sb.toString();
 1170   	}
 1171   
 1172   
 1173   	/**
 1174   	 * BeanPostProcessor that logs an info message when a bean is created during
 1175   	 * BeanPostProcessor instantiation, i.e. when a bean is not eligible for
 1176   	 * getting processed by all BeanPostProcessors.
 1177   	 */
 1178   	private class BeanPostProcessorChecker implements BeanPostProcessor {
 1179   
 1180   		private final ConfigurableListableBeanFactory beanFactory;
 1181   
 1182   		private final int beanPostProcessorTargetCount;
 1183   
 1184   		public BeanPostProcessorChecker(ConfigurableListableBeanFactory beanFactory, int beanPostProcessorTargetCount) {
 1185   			this.beanFactory = beanFactory;
 1186   			this.beanPostProcessorTargetCount = beanPostProcessorTargetCount;
 1187   		}
 1188   
 1189   		public Object postProcessBeforeInitialization(Object bean, String beanName) {
 1190   			return bean;
 1191   		}
 1192   
 1193   		public Object postProcessAfterInitialization(Object bean, String beanName) {
 1194   			if (!(bean instanceof BeanPostProcessor) &&
 1195   					this.beanFactory.getBeanPostProcessorCount() < this.beanPostProcessorTargetCount) {
 1196   				if (logger.isInfoEnabled()) {
 1197   					logger.info("Bean '" + beanName + "' is not eligible for getting processed by all " +
 1198   							"BeanPostProcessors (for example: not eligible for auto-proxying)");
 1199   				}
 1200   			}
 1201   			return bean;
 1202   		}
 1203   	}
 1204   
 1205   }

Save This Page
Home » spring-framework-2.5.5-with-dependencies » org.springframework » context » support » [javadoc | source]