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

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