0001: /*
0002: * Copyright 2002-2007 the original author or authors.
0003: *
0004: * Licensed under the Apache License, Version 2.0 (the "License");
0005: * you may not use this file except in compliance with the License.
0006: * You may obtain a copy of the License at
0007: *
0008: * http://www.apache.org/licenses/LICENSE-2.0
0009: *
0010: * Unless required by applicable law or agreed to in writing, software
0011: * distributed under the License is distributed on an "AS IS" BASIS,
0012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013: * See the License for the specific language governing permissions and
0014: * limitations under the License.
0015: */
0016:
0017: package org.springframework.context.support;
0018:
0019: import java.io.IOException;
0020: import java.util.ArrayList;
0021: import java.util.Collection;
0022: import java.util.Collections;
0023: import java.util.Date;
0024: import java.util.HashMap;
0025: import java.util.HashSet;
0026: import java.util.Iterator;
0027: import java.util.List;
0028: import java.util.Locale;
0029: import java.util.Map;
0030:
0031: import org.apache.commons.logging.Log;
0032: import org.apache.commons.logging.LogFactory;
0033:
0034: import org.springframework.beans.BeanUtils;
0035: import org.springframework.beans.BeansException;
0036: import org.springframework.beans.factory.BeanFactory;
0037: import org.springframework.beans.factory.BeanFactoryAware;
0038: import org.springframework.beans.factory.DisposableBean;
0039: import org.springframework.beans.factory.NoSuchBeanDefinitionException;
0040: import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
0041: import org.springframework.beans.factory.config.BeanDefinition;
0042: import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
0043: import org.springframework.beans.factory.config.BeanPostProcessor;
0044: import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
0045: import org.springframework.beans.factory.support.AbstractBeanDefinition;
0046: import org.springframework.beans.support.ResourceEditorRegistrar;
0047: import org.springframework.context.ApplicationContext;
0048: import org.springframework.context.ApplicationContextAware;
0049: import org.springframework.context.ApplicationEvent;
0050: import org.springframework.context.ApplicationEventPublisher;
0051: import org.springframework.context.ApplicationEventPublisherAware;
0052: import org.springframework.context.ApplicationListener;
0053: import org.springframework.context.ConfigurableApplicationContext;
0054: import org.springframework.context.HierarchicalMessageSource;
0055: import org.springframework.context.Lifecycle;
0056: import org.springframework.context.MessageSource;
0057: import org.springframework.context.MessageSourceAware;
0058: import org.springframework.context.MessageSourceResolvable;
0059: import org.springframework.context.NoSuchMessageException;
0060: import org.springframework.context.ResourceLoaderAware;
0061: import org.springframework.context.event.ApplicationEventMulticaster;
0062: import org.springframework.context.event.ContextClosedEvent;
0063: import org.springframework.context.event.ContextRefreshedEvent;
0064: import org.springframework.context.event.ContextStartedEvent;
0065: import org.springframework.context.event.ContextStoppedEvent;
0066: import org.springframework.context.event.SimpleApplicationEventMulticaster;
0067: import org.springframework.core.JdkVersion;
0068: import org.springframework.core.OrderComparator;
0069: import org.springframework.core.Ordered;
0070: import org.springframework.core.PriorityOrdered;
0071: import org.springframework.core.io.DefaultResourceLoader;
0072: import org.springframework.core.io.Resource;
0073: import org.springframework.core.io.ResourceLoader;
0074: import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
0075: import org.springframework.core.io.support.ResourcePatternResolver;
0076: import org.springframework.util.Assert;
0077: import org.springframework.util.ClassUtils;
0078: import org.springframework.util.ObjectUtils;
0079:
0080: /**
0081: * Abstract implementation of the {@link org.springframework.context.ApplicationContext}
0082: * interface. Doesn't mandate the type of storage used for configuration; simply
0083: * implements common context functionality. Uses the Template Method design pattern,
0084: * requiring concrete subclasses to implement abstract methods.
0085: *
0086: * <p>In contrast to a plain BeanFactory, an ApplicationContext is supposed
0087: * to detect special beans defined in its internal bean factory:
0088: * Therefore, this class automatically registers
0089: * {@link org.springframework.beans.factory.config.BeanFactoryPostProcessor BeanFactoryPostProcessors},
0090: * {@link org.springframework.beans.factory.config.BeanPostProcessor BeanPostProcessors}
0091: * and {@link org.springframework.context.ApplicationListener ApplicationListeners}
0092: * which are defined as beans in the context.
0093: *
0094: * <p>A {@link org.springframework.context.MessageSource} may also be supplied
0095: * as a bean in the context, with the name "messageSource"; else, message
0096: * resolution is delegated to the parent context. Furthermore, a multicaster
0097: * for application events can be supplied as "applicationEventMulticaster" bean
0098: * of type {@link org.springframework.context.event.ApplicationEventMulticaster}
0099: * in the context; else, a default multicaster of type
0100: * {@link org.springframework.context.event.SimpleApplicationEventMulticaster} will be used.
0101: *
0102: * <p>Implements resource loading through extending
0103: * {@link org.springframework.core.io.DefaultResourceLoader}.
0104: * Consequently treats non-URL resource paths as class path resources
0105: * (supporting full class path resource names that include the package path,
0106: * e.g. "mypackage/myresource.dat"), unless the {@link #getResourceByPath}
0107: * method is overwritten in a subclass.
0108: *
0109: * @author Rod Johnson
0110: * @author Juergen Hoeller
0111: * @author Mark Fisher
0112: * @since January 21, 2001
0113: * @see #refreshBeanFactory
0114: * @see #getBeanFactory
0115: * @see org.springframework.beans.factory.config.BeanFactoryPostProcessor
0116: * @see org.springframework.beans.factory.config.BeanPostProcessor
0117: * @see org.springframework.context.event.ApplicationEventMulticaster
0118: * @see org.springframework.context.ApplicationListener
0119: * @see org.springframework.context.MessageSource
0120: */
0121: public abstract class AbstractApplicationContext extends
0122: DefaultResourceLoader implements
0123: ConfigurableApplicationContext, DisposableBean {
0124:
0125: /**
0126: * Name of the MessageSource bean in the factory.
0127: * If none is supplied, message resolution is delegated to the parent.
0128: * @see MessageSource
0129: */
0130: public static final String MESSAGE_SOURCE_BEAN_NAME = "messageSource";
0131:
0132: /**
0133: * Name of the ApplicationEventMulticaster bean in the factory.
0134: * If none is supplied, a default SimpleApplicationEventMulticaster is used.
0135: * @see org.springframework.context.event.ApplicationEventMulticaster
0136: * @see org.springframework.context.event.SimpleApplicationEventMulticaster
0137: */
0138: public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
0139:
0140: static {
0141: // Eagerly load the ContextClosedEvent class to avoid weird classloader issues
0142: // on application shutdown in WebLogic 8.1. (Reported by Dustin Woods.)
0143: ContextClosedEvent.class.getName();
0144: }
0145:
0146: /** Logger used by this class. Available to subclasses. */
0147: protected final Log logger = LogFactory.getLog(getClass());
0148:
0149: /** Parent context */
0150: private ApplicationContext parent;
0151:
0152: /** BeanFactoryPostProcessors to apply on refresh */
0153: private final List beanFactoryPostProcessors = new ArrayList();
0154:
0155: /** Display name */
0156: private String displayName = ObjectUtils.identityToString(this );
0157:
0158: /** System time in milliseconds when this context started */
0159: private long startupDate;
0160:
0161: /** Flag that indicates whether this context is currently active */
0162: private boolean active = false;
0163:
0164: /** Synchronization monitor for the "active" flag */
0165: private final Object activeMonitor = new Object();
0166:
0167: /** Synchronization monitor for the "refresh" and "destroy" */
0168: private final Object startupShutdownMonitor = new Object();
0169:
0170: /** Reference to the JVM shutdown hook, if registered */
0171: private Thread shutdownHook;
0172:
0173: /** ResourcePatternResolver used by this context */
0174: private ResourcePatternResolver resourcePatternResolver;
0175:
0176: /** MessageSource we delegate our implementation of this interface to */
0177: private MessageSource messageSource;
0178:
0179: /** Helper class used in event publishing */
0180: private ApplicationEventMulticaster applicationEventMulticaster;
0181:
0182: /** Statically specified listeners */
0183: private List applicationListeners = new ArrayList();
0184:
0185: /**
0186: * Create a new AbstractApplicationContext with no parent.
0187: */
0188: public AbstractApplicationContext() {
0189: this (null);
0190: }
0191:
0192: /**
0193: * Create a new AbstractApplicationContext with the given parent context.
0194: * @param parent the parent context
0195: */
0196: public AbstractApplicationContext(ApplicationContext parent) {
0197: this .parent = parent;
0198: this .resourcePatternResolver = getResourcePatternResolver();
0199: }
0200:
0201: //---------------------------------------------------------------------
0202: // Implementation of ApplicationContext interface
0203: //---------------------------------------------------------------------
0204:
0205: /**
0206: * Return the parent context, or <code>null</code> if there is no parent
0207: * (that is, this context is the root of the context hierarchy).
0208: */
0209: public ApplicationContext getParent() {
0210: return this .parent;
0211: }
0212:
0213: /**
0214: * Return this context's internal bean factory as AutowireCapableBeanFactory,
0215: * if already available.
0216: * @see #getBeanFactory()
0217: */
0218: public AutowireCapableBeanFactory getAutowireCapableBeanFactory()
0219: throws IllegalStateException {
0220: return getBeanFactory();
0221: }
0222:
0223: /**
0224: * Set a friendly name for this context.
0225: * Typically done during initialization of concrete context implementations.
0226: */
0227: public void setDisplayName(String displayName) {
0228: this .displayName = displayName;
0229: }
0230:
0231: /**
0232: * Return a friendly name for this context.
0233: */
0234: public String getDisplayName() {
0235: return this .displayName;
0236: }
0237:
0238: /**
0239: * Return the timestamp (ms) when this context was first loaded.
0240: */
0241: public long getStartupDate() {
0242: return this .startupDate;
0243: }
0244:
0245: /**
0246: * Publish the given event to all listeners.
0247: * <p>Note: Listeners get initialized after the MessageSource, to be able
0248: * to access it within listener implementations. Thus, MessageSource
0249: * implementations cannot publish events.
0250: * @param event the event to publish (may be application-specific or a
0251: * standard framework event)
0252: */
0253: public void publishEvent(ApplicationEvent event) {
0254: Assert.notNull(event, "Event must not be null");
0255: if (logger.isDebugEnabled()) {
0256: logger.debug("Publishing event in context ["
0257: + ObjectUtils.identityToString(this ) + "]: "
0258: + event);
0259: }
0260: getApplicationEventMulticaster().multicastEvent(event);
0261: if (this .parent != null) {
0262: this .parent.publishEvent(event);
0263: }
0264: }
0265:
0266: /**
0267: * Return the internal MessageSource used by the context.
0268: * @return the internal MessageSource (never <code>null</code>)
0269: * @throws IllegalStateException if the context has not been initialized yet
0270: */
0271: private ApplicationEventMulticaster getApplicationEventMulticaster()
0272: throws IllegalStateException {
0273: if (this .applicationEventMulticaster == null) {
0274: throw new IllegalStateException(
0275: "ApplicationEventMulticaster not initialized - "
0276: + "call 'refresh' before multicasting events via the context: "
0277: + this );
0278: }
0279: return this .applicationEventMulticaster;
0280: }
0281:
0282: /**
0283: * Return the ResourcePatternResolver to use for resolving location patterns
0284: * into Resource instances. Default is a
0285: * {@link org.springframework.core.io.support.PathMatchingResourcePatternResolver},
0286: * supporting Ant-style location patterns.
0287: * <p>Can be overridden in subclasses, for extended resolution strategies,
0288: * for example in a web environment.
0289: * <p><b>Do not call this when needing to resolve a location pattern.</b>
0290: * Call the context's <code>getResources</code> method instead, which
0291: * will delegate to the ResourcePatternResolver.
0292: * @return the ResourcePatternResolver for this context
0293: * @see #getResources
0294: * @see org.springframework.core.io.support.PathMatchingResourcePatternResolver
0295: */
0296: protected ResourcePatternResolver getResourcePatternResolver() {
0297: return new PathMatchingResourcePatternResolver(this );
0298: }
0299:
0300: //---------------------------------------------------------------------
0301: // Implementation of ConfigurableApplicationContext interface
0302: //---------------------------------------------------------------------
0303:
0304: public void setParent(ApplicationContext parent) {
0305: this .parent = parent;
0306: }
0307:
0308: public void addBeanFactoryPostProcessor(
0309: BeanFactoryPostProcessor beanFactoryPostProcessor) {
0310: this .beanFactoryPostProcessors.add(beanFactoryPostProcessor);
0311: }
0312:
0313: /**
0314: * Return the list of BeanFactoryPostProcessors that will get applied
0315: * to the internal BeanFactory.
0316: * @see org.springframework.beans.factory.config.BeanFactoryPostProcessor
0317: */
0318: public List getBeanFactoryPostProcessors() {
0319: return this .beanFactoryPostProcessors;
0320: }
0321:
0322: public void addApplicationListener(ApplicationListener listener) {
0323: this .applicationListeners.add(listener);
0324: }
0325:
0326: /**
0327: * Return the list of statically specified ApplicationListeners.
0328: * @see org.springframework.context.ApplicationListener
0329: */
0330: public List getApplicationListeners() {
0331: return this .applicationListeners;
0332: }
0333:
0334: public void refresh() throws BeansException, IllegalStateException {
0335: synchronized (this .startupShutdownMonitor) {
0336: // Prepare this context for refreshing.
0337: prepareRefresh();
0338:
0339: // Tell the subclass to refresh the internal bean factory.
0340: ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
0341:
0342: // Prepare the bean factory for use in this context.
0343: prepareBeanFactory(beanFactory);
0344:
0345: try {
0346: // Allows post-processing of the bean factory in context subclasses.
0347: postProcessBeanFactory(beanFactory);
0348:
0349: // Invoke factory processors registered as beans in the context.
0350: invokeBeanFactoryPostProcessors(beanFactory);
0351:
0352: // Register bean processors that intercept bean creation.
0353: registerBeanPostProcessors(beanFactory);
0354:
0355: // Initialize message source for this context.
0356: initMessageSource();
0357:
0358: // Initialize event multicaster for this context.
0359: initApplicationEventMulticaster();
0360:
0361: // Initialize dependent beans for any lifecycle beans in this context.
0362: initLifecycleDependentBeans();
0363:
0364: // Initialize other special beans in specific context subclasses.
0365: onRefresh();
0366:
0367: // Check for listener beans and register them.
0368: registerListeners();
0369:
0370: // Instantiate all remaining (non-lazy-init) singletons.
0371: finishBeanFactoryInitialization(beanFactory);
0372:
0373: // Last step: publish corresponding event.
0374: finishRefresh();
0375: }
0376:
0377: catch (BeansException ex) {
0378: // Destroy already created singletons to avoid dangling resources.
0379: beanFactory.destroySingletons();
0380:
0381: // Reset 'active' flag.
0382: cancelRefresh(ex);
0383:
0384: // Propagate exception to caller.
0385: throw ex;
0386: }
0387: }
0388: }
0389:
0390: /**
0391: * Prepare this context for refreshing, setting its startup date and
0392: * active flag.
0393: */
0394: protected void prepareRefresh() {
0395: this .startupDate = System.currentTimeMillis();
0396:
0397: synchronized (this .activeMonitor) {
0398: this .active = true;
0399: }
0400:
0401: if (logger.isInfoEnabled()) {
0402: logger.info("Refreshing " + this );
0403: }
0404: }
0405:
0406: /**
0407: * Tell the subclass to refresh the internal bean factory.
0408: * @return the fresh BeanFactory instance
0409: * @see #refreshBeanFactory()
0410: * @see #getBeanFactory()
0411: */
0412: protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
0413: refreshBeanFactory();
0414: ConfigurableListableBeanFactory beanFactory = getBeanFactory();
0415:
0416: if (logger.isInfoEnabled()) {
0417: logger.info("Bean factory for application context ["
0418: + ObjectUtils.identityToString(this ) + "]: "
0419: + ObjectUtils.identityToString(beanFactory));
0420: }
0421: if (logger.isDebugEnabled()) {
0422: logger.debug(beanFactory.getBeanDefinitionCount()
0423: + " beans defined in " + this );
0424: }
0425:
0426: return beanFactory;
0427: }
0428:
0429: /**
0430: * Configure the factory's standard context characteristics,
0431: * such as the context's ClassLoader and post-processors.
0432: * @param beanFactory the BeanFactory to configure
0433: */
0434: protected void prepareBeanFactory(
0435: ConfigurableListableBeanFactory beanFactory) {
0436: // Tell the internal bean factory to use the context's class loader.
0437: beanFactory.setBeanClassLoader(getClassLoader());
0438:
0439: // Populate the bean factory with context-specific resource editors.
0440: beanFactory
0441: .addPropertyEditorRegistrar(new ResourceEditorRegistrar(
0442: this ));
0443:
0444: // Configure the bean factory with context callbacks.
0445: beanFactory
0446: .addBeanPostProcessor(new ApplicationContextAwareProcessor(
0447: this ));
0448: beanFactory
0449: .ignoreDependencyInterface(ResourceLoaderAware.class);
0450: beanFactory
0451: .ignoreDependencyInterface(ApplicationEventPublisherAware.class);
0452: beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
0453: beanFactory
0454: .ignoreDependencyInterface(ApplicationContextAware.class);
0455:
0456: // BeanFactory interface not registered as resolvable type in a plain factory.
0457: // MessageSource registered (and found for autowiring) as a bean.
0458: beanFactory.registerResolvableDependency(BeanFactory.class,
0459: beanFactory);
0460: beanFactory.registerResolvableDependency(ResourceLoader.class,
0461: this );
0462: beanFactory.registerResolvableDependency(
0463: ApplicationEventPublisher.class, this );
0464: beanFactory.registerResolvableDependency(
0465: ApplicationContext.class, this );
0466:
0467: // Detect a LoadTimeWeaver and prepare for weaving, if found.
0468: if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)
0469: && JdkVersion.isAtLeastJava15()) {
0470: // Register the (JDK 1.5 specific) LoadTimeWeaverAwareProcessor.
0471: try {
0472: Class ltwapClass = ClassUtils
0473: .forName(
0474: "org.springframework.context.weaving.LoadTimeWeaverAwareProcessor",
0475: getClass().getClassLoader());
0476: BeanPostProcessor ltwap = (BeanPostProcessor) BeanUtils
0477: .instantiateClass(ltwapClass);
0478: ((BeanFactoryAware) ltwap).setBeanFactory(beanFactory);
0479: beanFactory.addBeanPostProcessor(ltwap);
0480: } catch (ClassNotFoundException ex) {
0481: throw new IllegalStateException(
0482: "Spring's LoadTimeWeaverAwareProcessor class is not available");
0483: }
0484: // Set a temporary ClassLoader for type matching.
0485: beanFactory
0486: .setTempClassLoader(new ContextTypeMatchClassLoader(
0487: beanFactory.getBeanClassLoader()));
0488: }
0489: }
0490:
0491: /**
0492: * Modify the application context's internal bean factory after its standard
0493: * initialization. All bean definitions will have been loaded, but no beans
0494: * will have been instantiated yet. This allows for registering special
0495: * BeanPostProcessors etc in certain ApplicationContext implementations.
0496: * @param beanFactory the bean factory used by the application context
0497: */
0498: protected void postProcessBeanFactory(
0499: ConfigurableListableBeanFactory beanFactory) {
0500: }
0501:
0502: /**
0503: * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
0504: * respecting explicit order if given.
0505: * <p>Must be called before singleton instantiation.
0506: */
0507: protected void invokeBeanFactoryPostProcessors(
0508: ConfigurableListableBeanFactory beanFactory) {
0509: // Invoke factory processors registered with the context instance.
0510: for (Iterator it = getBeanFactoryPostProcessors().iterator(); it
0511: .hasNext();) {
0512: BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor) it
0513: .next();
0514: factoryProcessor.postProcessBeanFactory(beanFactory);
0515: }
0516:
0517: // Do not initialize FactoryBeans here: We need to leave all regular beans
0518: // uninitialized to let the bean factory post-processors apply to them!
0519: String[] postProcessorNames = beanFactory.getBeanNamesForType(
0520: BeanFactoryPostProcessor.class, true, false);
0521:
0522: // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
0523: // Ordered, and the rest.
0524: List priorityOrderedPostProcessors = new ArrayList();
0525: List orderedPostProcessorNames = new ArrayList();
0526: List nonOrderedPostProcessorNames = new ArrayList();
0527: for (int i = 0; i < postProcessorNames.length; i++) {
0528: if (isTypeMatch(postProcessorNames[i],
0529: PriorityOrdered.class)) {
0530: priorityOrderedPostProcessors.add(beanFactory
0531: .getBean(postProcessorNames[i]));
0532: } else if (isTypeMatch(postProcessorNames[i], Ordered.class)) {
0533: orderedPostProcessorNames.add(postProcessorNames[i]);
0534: } else {
0535: nonOrderedPostProcessorNames.add(postProcessorNames[i]);
0536: }
0537: }
0538:
0539: // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
0540: Collections.sort(priorityOrderedPostProcessors,
0541: new OrderComparator());
0542: invokeBeanFactoryPostProcessors(beanFactory,
0543: priorityOrderedPostProcessors);
0544:
0545: // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
0546: List orderedPostProcessors = new ArrayList();
0547: for (Iterator it = orderedPostProcessorNames.iterator(); it
0548: .hasNext();) {
0549: String postProcessorName = (String) it.next();
0550: orderedPostProcessors.add(getBean(postProcessorName));
0551: }
0552: Collections.sort(orderedPostProcessors, new OrderComparator());
0553: invokeBeanFactoryPostProcessors(beanFactory,
0554: orderedPostProcessors);
0555:
0556: // Finally, invoke all other BeanFactoryPostProcessors.
0557: List nonOrderedPostProcessors = new ArrayList();
0558: for (Iterator it = nonOrderedPostProcessorNames.iterator(); it
0559: .hasNext();) {
0560: String postProcessorName = (String) it.next();
0561: nonOrderedPostProcessors.add(getBean(postProcessorName));
0562: }
0563: invokeBeanFactoryPostProcessors(beanFactory,
0564: nonOrderedPostProcessors);
0565: }
0566:
0567: /**
0568: * Invoke the given BeanFactoryPostProcessor beans.
0569: */
0570: private void invokeBeanFactoryPostProcessors(
0571: ConfigurableListableBeanFactory beanFactory,
0572: List postProcessors) {
0573: for (Iterator it = postProcessors.iterator(); it.hasNext();) {
0574: BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor) it
0575: .next();
0576: postProcessor.postProcessBeanFactory(beanFactory);
0577: }
0578: }
0579:
0580: /**
0581: * Instantiate and invoke all registered BeanPostProcessor beans,
0582: * respecting explicit order if given.
0583: * <p>Must be called before any instantiation of application beans.
0584: */
0585: protected void registerBeanPostProcessors(
0586: ConfigurableListableBeanFactory beanFactory) {
0587: String[] postProcessorNames = beanFactory.getBeanNamesForType(
0588: BeanPostProcessor.class, true, false);
0589:
0590: // Register BeanPostProcessorChecker that logs an info message when
0591: // a bean is created during BeanPostProcessor instantiation, i.e. when
0592: // a bean is not eligible for getting processed by all BeanPostProcessors.
0593: int beanProcessorTargetCount = beanFactory
0594: .getBeanPostProcessorCount()
0595: + 1 + postProcessorNames.length;
0596: beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(
0597: beanFactory, beanProcessorTargetCount));
0598:
0599: // Separate between BeanPostProcessors that implement PriorityOrdered,
0600: // Ordered, and the rest.
0601: List priorityOrderedPostProcessors = new ArrayList();
0602: List orderedPostProcessorNames = new ArrayList();
0603: List nonOrderedPostProcessorNames = new ArrayList();
0604: for (int i = 0; i < postProcessorNames.length; i++) {
0605: if (isTypeMatch(postProcessorNames[i],
0606: PriorityOrdered.class)) {
0607: priorityOrderedPostProcessors.add(beanFactory
0608: .getBean(postProcessorNames[i]));
0609: } else if (isTypeMatch(postProcessorNames[i], Ordered.class)) {
0610: orderedPostProcessorNames.add(postProcessorNames[i]);
0611: } else {
0612: nonOrderedPostProcessorNames.add(postProcessorNames[i]);
0613: }
0614: }
0615:
0616: // First, invoke the BeanPostProcessors that implement PriorityOrdered.
0617: Collections.sort(priorityOrderedPostProcessors,
0618: new OrderComparator());
0619: registerBeanPostProcessors(beanFactory,
0620: priorityOrderedPostProcessors);
0621:
0622: // Next, invoke the BeanPostProcessors that implement Ordered.
0623: List orderedPostProcessors = new ArrayList();
0624: for (Iterator it = orderedPostProcessorNames.iterator(); it
0625: .hasNext();) {
0626: String postProcessorName = (String) it.next();
0627: orderedPostProcessors.add(getBean(postProcessorName));
0628: }
0629: Collections.sort(orderedPostProcessors, new OrderComparator());
0630: registerBeanPostProcessors(beanFactory, orderedPostProcessors);
0631:
0632: // Finally, invoke all other BeanPostProcessors.
0633: List nonOrderedPostProcessors = new ArrayList();
0634: for (Iterator it = nonOrderedPostProcessorNames.iterator(); it
0635: .hasNext();) {
0636: String postProcessorName = (String) it.next();
0637: nonOrderedPostProcessors.add(getBean(postProcessorName));
0638: }
0639: registerBeanPostProcessors(beanFactory,
0640: nonOrderedPostProcessors);
0641: }
0642:
0643: /**
0644: * Register the given BeanPostProcessor beans.
0645: */
0646: private void registerBeanPostProcessors(
0647: ConfigurableListableBeanFactory beanFactory,
0648: List postProcessors) {
0649: for (Iterator it = postProcessors.iterator(); it.hasNext();) {
0650: BeanPostProcessor postProcessor = (BeanPostProcessor) it
0651: .next();
0652: beanFactory.addBeanPostProcessor(postProcessor);
0653: }
0654: }
0655:
0656: /**
0657: * Initialize the MessageSource.
0658: * Use parent's if none defined in this context.
0659: */
0660: protected void initMessageSource() {
0661: ConfigurableListableBeanFactory beanFactory = getBeanFactory();
0662: if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
0663: this .messageSource = (MessageSource) beanFactory.getBean(
0664: MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
0665: // Make MessageSource aware of parent MessageSource.
0666: if (this .parent != null
0667: && this .messageSource instanceof HierarchicalMessageSource) {
0668: HierarchicalMessageSource hms = (HierarchicalMessageSource) this .messageSource;
0669: if (hms.getParentMessageSource() == null) {
0670: // Only set parent context as parent MessageSource if no parent MessageSource
0671: // registered already.
0672: hms
0673: .setParentMessageSource(getInternalParentMessageSource());
0674: }
0675: }
0676: if (logger.isDebugEnabled()) {
0677: logger.debug("Using MessageSource ["
0678: + this .messageSource + "]");
0679: }
0680: } else {
0681: // Use empty MessageSource to be able to accept getMessage calls.
0682: DelegatingMessageSource dms = new DelegatingMessageSource();
0683: dms
0684: .setParentMessageSource(getInternalParentMessageSource());
0685: this .messageSource = dms;
0686: beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME,
0687: this .messageSource);
0688: if (logger.isDebugEnabled()) {
0689: logger
0690: .debug("Unable to locate MessageSource with name '"
0691: + MESSAGE_SOURCE_BEAN_NAME
0692: + "': using default ["
0693: + this .messageSource + "]");
0694: }
0695: }
0696: }
0697:
0698: /**
0699: * Initialize the ApplicationEventMulticaster.
0700: * Uses SimpleApplicationEventMulticaster if none defined in the context.
0701: * @see org.springframework.context.event.SimpleApplicationEventMulticaster
0702: */
0703: protected void initApplicationEventMulticaster() {
0704: ConfigurableListableBeanFactory beanFactory = getBeanFactory();
0705: if (beanFactory
0706: .containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
0707: this .applicationEventMulticaster = (ApplicationEventMulticaster) beanFactory
0708: .getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME,
0709: ApplicationEventMulticaster.class);
0710: if (logger.isDebugEnabled()) {
0711: logger.debug("Using ApplicationEventMulticaster ["
0712: + this .applicationEventMulticaster + "]");
0713: }
0714: } else {
0715: this .applicationEventMulticaster = new SimpleApplicationEventMulticaster();
0716: beanFactory.registerSingleton(
0717: APPLICATION_EVENT_MULTICASTER_BEAN_NAME,
0718: this .applicationEventMulticaster);
0719: if (logger.isDebugEnabled()) {
0720: logger
0721: .debug("Unable to locate ApplicationEventMulticaster with name '"
0722: + APPLICATION_EVENT_MULTICASTER_BEAN_NAME
0723: + "': using default ["
0724: + this .applicationEventMulticaster
0725: + "]");
0726: }
0727: }
0728: }
0729:
0730: /**
0731: * Registers dependent beans for any singleton lifecycle beans in this
0732: * context, thus ensuring they are started and stopped in the correct order.
0733: */
0734: protected void initLifecycleDependentBeans() {
0735: String lifecycleBeans[] = this .getBeanNamesForType(
0736: Lifecycle.class, false, false);
0737: for (int i = 0; i < lifecycleBeans.length; i++) {
0738: String beanName = lifecycleBeans[i];
0739: if (getBeanFactory().containsBeanDefinition(beanName)) {
0740: BeanDefinition bd = getBeanFactory().getBeanDefinition(
0741: beanName);
0742: if (bd instanceof AbstractBeanDefinition) {
0743: String[] dependsOn = ((AbstractBeanDefinition) bd)
0744: .getDependsOn();
0745: if (dependsOn != null) {
0746: for (int j = 0; j < dependsOn.length; j++) {
0747: getBeanFactory().registerDependentBean(
0748: dependsOn[j], beanName);
0749: }
0750: }
0751: }
0752: }
0753: }
0754: }
0755:
0756: /**
0757: * Template method which can be overridden to add context-specific refresh work.
0758: * Called on initialization of special beans, before instantiation of singletons.
0759: * <p>This implementation is empty.
0760: * @throws BeansException in case of errors
0761: * @see #refresh()
0762: */
0763: protected void onRefresh() throws BeansException {
0764: // For subclasses: do nothing by default.
0765: }
0766:
0767: /**
0768: * Add beans that implement ApplicationListener as listeners.
0769: * Doesn't affect other listeners, which can be added without being beans.
0770: */
0771: protected void registerListeners() {
0772: // Register statically specified listeners first.
0773: for (Iterator it = getApplicationListeners().iterator(); it
0774: .hasNext();) {
0775: addListener((ApplicationListener) it.next());
0776: }
0777: // Do not initialize FactoryBeans here: We need to leave all regular beans
0778: // uninitialized to let post-processors apply to them!
0779: Collection listenerBeans = getBeansOfType(
0780: ApplicationListener.class, true, false).values();
0781: for (Iterator it = listenerBeans.iterator(); it.hasNext();) {
0782: addListener((ApplicationListener) it.next());
0783: }
0784: }
0785:
0786: /**
0787: * Subclasses can invoke this method to register a listener.
0788: * Any beans in the context that are listeners are automatically added.
0789: * @param listener the listener to register
0790: */
0791: protected void addListener(ApplicationListener listener) {
0792: getApplicationEventMulticaster().addApplicationListener(
0793: listener);
0794: }
0795:
0796: /**
0797: * Finish the initialization of this context's bean factory,
0798: * initializing all remaining singleton beans.
0799: */
0800: protected void finishBeanFactoryInitialization(
0801: ConfigurableListableBeanFactory beanFactory) {
0802: // Stop using the temporary ClassLoader for type matching.
0803: beanFactory.setTempClassLoader(null);
0804:
0805: // Instantiate all remaining (non-lazy-init) singletons.
0806: beanFactory.preInstantiateSingletons();
0807: }
0808:
0809: /**
0810: * Finish the refresh of this context, publishing the
0811: * {@link org.springframework.context.event.ContextRefreshedEvent}.
0812: */
0813: protected void finishRefresh() {
0814: publishEvent(new ContextRefreshedEvent(this ));
0815: }
0816:
0817: /**
0818: * Cancel this context's refresh attempt, resetting the <code>active</code> flag
0819: * after an exception got thrown.
0820: * @param ex the exception that led to the cancellation
0821: */
0822: protected void cancelRefresh(BeansException ex) {
0823: synchronized (this .activeMonitor) {
0824: this .active = false;
0825: }
0826: }
0827:
0828: /**
0829: * Register a shutdown hook with the JVM runtime, closing this context
0830: * on JVM shutdown unless it has already been closed at that time.
0831: * <p>Delegates to <code>doClose()</code> for the actual closing procedure.
0832: * @see java.lang.Runtime#addShutdownHook
0833: * @see #close()
0834: * @see #doClose()
0835: */
0836: public void registerShutdownHook() {
0837: if (this .shutdownHook == null) {
0838: // No shutdown hook registered yet.
0839: this .shutdownHook = new Thread() {
0840: public void run() {
0841: doClose();
0842: }
0843: };
0844: Runtime.getRuntime().addShutdownHook(this .shutdownHook);
0845: }
0846: }
0847:
0848: /**
0849: * DisposableBean callback for destruction of this instance.
0850: * Only called when the ApplicationContext itself is running
0851: * as a bean in another BeanFactory or ApplicationContext,
0852: * which is rather unusual.
0853: * <p>The <code>close</code> method is the native way to
0854: * shut down an ApplicationContext.
0855: * @see #close()
0856: * @see org.springframework.beans.factory.access.SingletonBeanFactoryLocator
0857: */
0858: public void destroy() {
0859: close();
0860: }
0861:
0862: /**
0863: * Close this application context, destroying all beans in its bean factory.
0864: * <p>Delegates to <code>doClose()</code> for the actual closing procedure.
0865: * Also removes a JVM shutdown hook, if registered, as it's not needed anymore.
0866: * @see #doClose()
0867: * @see #registerShutdownHook()
0868: */
0869: public void close() {
0870: synchronized (this .startupShutdownMonitor) {
0871: doClose();
0872: // If we registered a JVM shutdown hook, we don't need it anymore now:
0873: // We've already explicitly closed the context.
0874: if (this .shutdownHook != null) {
0875: Runtime.getRuntime().removeShutdownHook(
0876: this .shutdownHook);
0877: }
0878: }
0879: }
0880:
0881: /**
0882: * Actually performs context closing: publishes a ContextClosedEvent and
0883: * destroys the singletons in the bean factory of this application context.
0884: * <p>Called by both <code>close()</code> and a JVM shutdown hook, if any.
0885: * @see org.springframework.context.event.ContextClosedEvent
0886: * @see org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons()
0887: * @see #close()
0888: * @see #registerShutdownHook()
0889: */
0890: protected void doClose() {
0891: if (isActive()) {
0892: if (logger.isInfoEnabled()) {
0893: logger.info("Closing " + this );
0894: }
0895: try {
0896: // Publish shutdown event.
0897: publishEvent(new ContextClosedEvent(this ));
0898: } catch (Throwable ex) {
0899: logger
0900: .error(
0901: "Exception thrown from ApplicationListener handling ContextClosedEvent",
0902: ex);
0903: }
0904: // Stop all Lifecycle beans, to avoid delays during individual destruction.
0905: stop();
0906: // Destroy all cached singletons in the context's BeanFactory.
0907: destroyBeans();
0908: // Close the state of this context itself.
0909: closeBeanFactory();
0910: onClose();
0911: synchronized (this .activeMonitor) {
0912: this .active = false;
0913: }
0914: }
0915: }
0916:
0917: /**
0918: * Template method for destroying all beans that this context manages.
0919: * The default implementation destroy all cached singletons in this context,
0920: * invoking <code>DisposableBean.destroy()</code> and/or the specified
0921: * "destroy-method".
0922: * <p>Can be overridden to add context-specific bean destruction steps
0923: * right before or right after standard singleton destruction,
0924: * while the context's BeanFactory is still active.
0925: * @see #getBeanFactory()
0926: * @see org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons()
0927: */
0928: protected void destroyBeans() {
0929: getBeanFactory().destroySingletons();
0930: }
0931:
0932: /**
0933: * Template method which can be overridden to add context-specific shutdown work.
0934: * The default implementation is empty.
0935: * <p>Called at the end of {@link #doClose}'s shutdown procedure, after
0936: * this context's BeanFactory has been closed. If custom shutdown logic
0937: * needs to execute while the BeanFactory is still active, override
0938: * the {@link #destroyBeans()} method instead.
0939: */
0940: protected void onClose() {
0941: // For subclasses: do nothing by default.
0942: }
0943:
0944: public boolean isActive() {
0945: synchronized (this .activeMonitor) {
0946: return this .active;
0947: }
0948: }
0949:
0950: //---------------------------------------------------------------------
0951: // Implementation of BeanFactory interface
0952: //---------------------------------------------------------------------
0953:
0954: public Object getBean(String name) throws BeansException {
0955: return getBeanFactory().getBean(name);
0956: }
0957:
0958: public Object getBean(String name, Class requiredType)
0959: throws BeansException {
0960: return getBeanFactory().getBean(name, requiredType);
0961: }
0962:
0963: public Object getBean(String name, Object[] args)
0964: throws BeansException {
0965: return getBeanFactory().getBean(name, args);
0966: }
0967:
0968: public boolean containsBean(String name) {
0969: return getBeanFactory().containsBean(name);
0970: }
0971:
0972: public boolean isSingleton(String name)
0973: throws NoSuchBeanDefinitionException {
0974: return getBeanFactory().isSingleton(name);
0975: }
0976:
0977: public boolean isPrototype(String name)
0978: throws NoSuchBeanDefinitionException {
0979: return getBeanFactory().isPrototype(name);
0980: }
0981:
0982: public boolean isTypeMatch(String name, Class targetType)
0983: throws NoSuchBeanDefinitionException {
0984: return getBeanFactory().isTypeMatch(name, targetType);
0985: }
0986:
0987: public Class getType(String name)
0988: throws NoSuchBeanDefinitionException {
0989: return getBeanFactory().getType(name);
0990: }
0991:
0992: public String[] getAliases(String name) {
0993: return getBeanFactory().getAliases(name);
0994: }
0995:
0996: //---------------------------------------------------------------------
0997: // Implementation of ListableBeanFactory interface
0998: //---------------------------------------------------------------------
0999:
1000: public boolean containsBeanDefinition(String name) {
1001: return getBeanFactory().containsBeanDefinition(name);
1002: }
1003:
1004: public int getBeanDefinitionCount() {
1005: return getBeanFactory().getBeanDefinitionCount();
1006: }
1007:
1008: public String[] getBeanDefinitionNames() {
1009: return getBeanFactory().getBeanDefinitionNames();
1010: }
1011:
1012: public String[] getBeanNamesForType(Class type) {
1013: return getBeanFactory().getBeanNamesForType(type);
1014: }
1015:
1016: public String[] getBeanNamesForType(Class type,
1017: boolean includePrototypes, boolean allowEagerInit) {
1018: return getBeanFactory().getBeanNamesForType(type,
1019: includePrototypes, allowEagerInit);
1020: }
1021:
1022: public Map getBeansOfType(Class type) throws BeansException {
1023: return getBeanFactory().getBeansOfType(type);
1024: }
1025:
1026: public Map getBeansOfType(Class type, boolean includePrototypes,
1027: boolean allowEagerInit) throws BeansException {
1028:
1029: return getBeanFactory().getBeansOfType(type, includePrototypes,
1030: allowEagerInit);
1031: }
1032:
1033: //---------------------------------------------------------------------
1034: // Implementation of HierarchicalBeanFactory interface
1035: //---------------------------------------------------------------------
1036:
1037: public BeanFactory getParentBeanFactory() {
1038: return getParent();
1039: }
1040:
1041: public boolean containsLocalBean(String name) {
1042: return getBeanFactory().containsLocalBean(name);
1043: }
1044:
1045: /**
1046: * Return the internal bean factory of the parent context if it implements
1047: * ConfigurableApplicationContext; else, return the parent context itself.
1048: * @see org.springframework.context.ConfigurableApplicationContext#getBeanFactory
1049: */
1050: protected BeanFactory getInternalParentBeanFactory() {
1051: return (getParent() instanceof ConfigurableApplicationContext) ? ((ConfigurableApplicationContext) getParent())
1052: .getBeanFactory()
1053: : (BeanFactory) getParent();
1054: }
1055:
1056: //---------------------------------------------------------------------
1057: // Implementation of MessageSource interface
1058: //---------------------------------------------------------------------
1059:
1060: public String getMessage(String code, Object args[],
1061: String defaultMessage, Locale locale) {
1062: return getMessageSource().getMessage(code, args,
1063: defaultMessage, locale);
1064: }
1065:
1066: public String getMessage(String code, Object args[], Locale locale)
1067: throws NoSuchMessageException {
1068: return getMessageSource().getMessage(code, args, locale);
1069: }
1070:
1071: public String getMessage(MessageSourceResolvable resolvable,
1072: Locale locale) throws NoSuchMessageException {
1073: return getMessageSource().getMessage(resolvable, locale);
1074: }
1075:
1076: /**
1077: * Return the internal MessageSource used by the context.
1078: * @return the internal MessageSource (never <code>null</code>)
1079: * @throws IllegalStateException if the context has not been initialized yet
1080: */
1081: private MessageSource getMessageSource()
1082: throws IllegalStateException {
1083: if (this .messageSource == null) {
1084: throw new IllegalStateException(
1085: "MessageSource not initialized - "
1086: + "call 'refresh' before accessing messages via the context: "
1087: + this );
1088: }
1089: return this .messageSource;
1090: }
1091:
1092: /**
1093: * Return the internal message source of the parent context if it is an
1094: * AbstractApplicationContext too; else, return the parent context itself.
1095: */
1096: protected MessageSource getInternalParentMessageSource() {
1097: return (getParent() instanceof AbstractApplicationContext) ? ((AbstractApplicationContext) getParent()).messageSource
1098: : getParent();
1099: }
1100:
1101: //---------------------------------------------------------------------
1102: // Implementation of ResourcePatternResolver interface
1103: //---------------------------------------------------------------------
1104:
1105: public Resource[] getResources(String locationPattern)
1106: throws IOException {
1107: return this .resourcePatternResolver
1108: .getResources(locationPattern);
1109: }
1110:
1111: //---------------------------------------------------------------------
1112: // Implementation of Lifecycle interface
1113: //---------------------------------------------------------------------
1114:
1115: public void start() {
1116: Map lifecycleBeans = getLifecycleBeans();
1117: for (Iterator it = new HashSet(lifecycleBeans.keySet())
1118: .iterator(); it.hasNext();) {
1119: String beanName = (String) it.next();
1120: doStart(lifecycleBeans, beanName);
1121: }
1122: publishEvent(new ContextStartedEvent(this ));
1123: }
1124:
1125: public void stop() {
1126: Map lifecycleBeans = getLifecycleBeans();
1127: for (Iterator it = new HashSet(lifecycleBeans.keySet())
1128: .iterator(); it.hasNext();) {
1129: String beanName = (String) it.next();
1130: doStop(lifecycleBeans, beanName);
1131: }
1132: publishEvent(new ContextStoppedEvent(this ));
1133: }
1134:
1135: public boolean isRunning() {
1136: Iterator it = getLifecycleBeans().values().iterator();
1137: while (it.hasNext()) {
1138: Lifecycle lifecycle = (Lifecycle) it.next();
1139: if (!lifecycle.isRunning()) {
1140: return false;
1141: }
1142: }
1143: return true;
1144: }
1145:
1146: /**
1147: * Return a Map of all singleton beans that implement the
1148: * Lifecycle interface in this context.
1149: * @return Map of Lifecycle beans with bean name as key
1150: */
1151: private Map getLifecycleBeans() {
1152: ConfigurableListableBeanFactory beanFactory = getBeanFactory();
1153: String[] beanNames = beanFactory.getBeanNamesForType(
1154: Lifecycle.class, false, false);
1155: Map beans = new HashMap(beanNames.length);
1156: for (int i = 0; i < beanNames.length; i++) {
1157: Object bean = beanFactory.getSingleton(beanNames[i]);
1158: if (bean != null) {
1159: beans.put(beanNames[i], bean);
1160: }
1161: }
1162: return beans;
1163: }
1164:
1165: /**
1166: * Start the specified bean as part of the given set of Lifecycle beans,
1167: * making sure that any beans that it depends on are started first.
1168: * @param lifecycleBeans Map with bean name as key and Lifecycle instance as value
1169: * @param beanName the name of the bean to start
1170: */
1171: private void doStart(Map lifecycleBeans, String beanName) {
1172: Lifecycle bean = (Lifecycle) lifecycleBeans.get(beanName);
1173: if (bean != null) {
1174: String[] dependenciesForBean = getBeanFactory()
1175: .getDependenciesForBean(beanName);
1176: for (int i = 0; i < dependenciesForBean.length; i++) {
1177: doStart(lifecycleBeans, dependenciesForBean[i]);
1178: }
1179: if (!bean.isRunning()) {
1180: bean.start();
1181: }
1182: lifecycleBeans.remove(beanName);
1183: }
1184: }
1185:
1186: /**
1187: * Stop the specified bean as part of the given set of Lifecycle beans,
1188: * making sure that any beans that depends on it are stopped first.
1189: * @param lifecycleBeans Map with bean name as key and Lifecycle instance as value
1190: * @param beanName the name of the bean to stop
1191: */
1192: private void doStop(Map lifecycleBeans, String beanName) {
1193: Lifecycle bean = (Lifecycle) lifecycleBeans.get(beanName);
1194: if (bean != null) {
1195: String[] dependentBeans = getBeanFactory()
1196: .getDependentBeans(beanName);
1197: for (int i = 0; i < dependentBeans.length; i++) {
1198: doStop(lifecycleBeans, dependentBeans[i]);
1199: }
1200: if (bean.isRunning()) {
1201: bean.stop();
1202: }
1203: lifecycleBeans.remove(beanName);
1204: }
1205: }
1206:
1207: //---------------------------------------------------------------------
1208: // Abstract methods that must be implemented by subclasses
1209: //---------------------------------------------------------------------
1210:
1211: /**
1212: * Subclasses must implement this method to perform the actual configuration load.
1213: * The method is invoked by {@link #refresh()} before any other initialization work.
1214: * <p>A subclass will either create a new bean factory and hold a reference to it,
1215: * or return a single BeanFactory instance that it holds. In the latter case, it will
1216: * usually throw an IllegalStateException if refreshing the context more than once.
1217: * @throws BeansException if initialization of the bean factory failed
1218: * @throws IllegalStateException if already initialized and multiple refresh
1219: * attempts are not supported
1220: */
1221: protected abstract void refreshBeanFactory() throws BeansException,
1222: IllegalStateException;
1223:
1224: /**
1225: * Subclasses must implement this method to release their internal bean factory.
1226: * This method gets invoked by {@link #close()} after all other shutdown work.
1227: * <p>Should never throw an exception but rather log shutdown failures.
1228: */
1229: protected abstract void closeBeanFactory();
1230:
1231: /**
1232: * Subclasses must return their internal bean factory here. They should implement the
1233: * lookup efficiently, so that it can be called repeatedly without a performance penalty.
1234: * <p>Note: Subclasses should check whether the context is still active before
1235: * returning the internal bean factory. The internal factory should generally be
1236: * considered unavailable once the context has been closed.
1237: * @return this application context's internal bean factory (never <code>null</code>)
1238: * @throws IllegalStateException if the context does not hold an internal bean factory yet
1239: * (usually if {@link #refresh()} has never been called) or if the context has been
1240: * closed already
1241: * @see #refreshBeanFactory()
1242: * @see #closeBeanFactory()
1243: */
1244: public abstract ConfigurableListableBeanFactory getBeanFactory()
1245: throws IllegalStateException;
1246:
1247: /**
1248: * Return information about this context.
1249: */
1250: public String toString() {
1251: StringBuffer sb = new StringBuffer(ObjectUtils
1252: .identityToString(this ));
1253: sb.append(": display name [").append(getDisplayName());
1254: sb.append("]; startup date [").append(
1255: new Date(getStartupDate()));
1256: sb.append("]; ");
1257: ApplicationContext parent = getParent();
1258: if (parent == null) {
1259: sb.append("root of context hierarchy");
1260: } else {
1261: sb.append("parent: ").append(
1262: ObjectUtils.identityToString(parent));
1263: }
1264: return sb.toString();
1265: }
1266:
1267: /**
1268: * BeanPostProcessor that logs an info message when a bean is created during
1269: * BeanPostProcessor instantiation, i.e. when a bean is not eligible for
1270: * getting processed by all BeanPostProcessors.
1271: */
1272: private class BeanPostProcessorChecker implements BeanPostProcessor {
1273:
1274: private final ConfigurableListableBeanFactory beanFactory;
1275:
1276: private final int beanPostProcessorTargetCount;
1277:
1278: public BeanPostProcessorChecker(
1279: ConfigurableListableBeanFactory beanFactory,
1280: int beanPostProcessorTargetCount) {
1281: this .beanFactory = beanFactory;
1282: this .beanPostProcessorTargetCount = beanPostProcessorTargetCount;
1283: }
1284:
1285: public Object postProcessBeforeInitialization(Object bean,
1286: String beanName) {
1287: return bean;
1288: }
1289:
1290: public Object postProcessAfterInitialization(Object bean,
1291: String beanName) {
1292: if (!(bean instanceof BeanPostProcessor)
1293: && this .beanFactory.getBeanPostProcessorCount() < this .beanPostProcessorTargetCount) {
1294: if (logger.isInfoEnabled()) {
1295: logger
1296: .info("Bean '"
1297: + beanName
1298: + "' is not eligible for getting processed by all "
1299: + "BeanPostProcessors (for example: not eligible for auto-proxying)");
1300: }
1301: }
1302: return bean;
1303: }
1304: }
1305:
1306: }
|