spring源码阅读笔记之HelloWorld和spring第一步ClassPathXMLApplicationContext
Posted 忧伤的可乐鸡
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring源码阅读笔记之HelloWorld和spring第一步ClassPathXMLApplicationContext相关的知识,希望对你有一定的参考价值。
文章目录
spring源码阅读
第一次读spring源码,先从这一段代码开始(基于5.1.3.RELEASE)。
public static void main(String[] args)
ApplicationContext ct=new ClassPathXmlApplicationContext("applicationContext.xml");
HelloService helloService = (HelloService)ct.getBean("hello");
helloService.hello();
这段代码加载了配置文件,并获取了bean,我们这一篇先看看如何加载的配置文件,以及spring加载配置的一个大体的流程和涉及到哪些接口,哪些类。
整体结构
稍后,我们将一一介绍这些类和接口的作用和扮演的角色。
ClassPathXmlApplicationContext
所属包:org.springframework.context.support
先阅读以下该类的官方注释
/**
* Standalone XML application context, taking the context definition files
* from the class path, interpreting plain paths as class path resource names
* that include the package path (e.g. "mypackage/myresource.txt"). Useful for
* test harnesses as well as for application contexts embedded within JARs.
*
* <p>The config location defaults can be overridden via @link #getConfigLocations,
* Config locations can either denote concrete files like "/myfiles/context.xml"
* or Ant-style patterns like "/myfiles/*-context.xml" (see the
* @link org.springframework.util.AntPathMatcher javadoc for pattern details).
*
* <p>Note: In case of multiple config locations, later bean definitions will
* override ones defined in earlier loaded files. This can be leveraged to
* deliberately override certain bean definitions via an extra XML file.
*
* <p><b>This is a simple, one-stop shop convenience ApplicationContext.
* Consider using the @link GenericApplicationContext class in combination
* with an @link org.springframework.beans.factory.xml.XmlBeanDefinitionReader
* for more flexible context setup.</b>
*
* @author Rod Johnson
* @author Juergen Hoeller
* @see #getResource
* @see #getResourceByPath
* @see GenericApplicationContext
*/
翻译一波
/**
* 单例的XML应用程序上下文,获取上下文定义文件
* 从类路径中,将普通路径解释为类路径资源名称
* 包括包路径(例如“mypackage / myresource.txt”)。
* 适用于测试工具以及JAR中嵌入的应用程序上下文。
*
* <p>配置位置默认值可以通过@link #getConfigLocations覆盖,
* 配置位置可以表示具体文件,如“/myfiles/context.xml”或Ant样式模式,
* 如“/myfiles/*-context.xml”(参见 @link org.springframework.util.AntPathMatcher
* javadoc用于模式详细信息)。
* ps:getConfigLocations在其父类AbstractRefreshableApplicationContext中
*
* <p>注意:如果有多个配置位置,以后的bean定义将覆盖先前
* 加载的文件中定义的bean定义。 这可以用来通过额外的XML文件故意覆盖某些bean定义。
*
* <p><b>这是一个简单的一站式便利ApplicationContext。
* 考虑将@link GenericApplicationContext类与@link
* org.springframework.beans.factory.xml.XmlBeanDefinitionReader结合使用,
* 以实现更灵活的上下文设置。</b>
*
* ps:这个类是一个简单的加载配置文件的context,理解spring,从这里是第一步。
* 这个类更多的是入口,里面并没有做什么逻辑操作,真正处理的方法都在他的父类中
*
* @author Rod Johnson
* @author Juergen Hoeller
* @see #getResource
* @see #getResourceByPath
* @see GenericApplicationContext
*/
现在我们看下这个类的部分源码,以及里面的方法和实现,spring第一步ClassPathXMLApplicationContext。
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext
/**
* Create a new ClassPathXmlApplicationContext, loading the definitions
* from the given XML file and automatically refreshing the context.
* @param configLocation resource location
* @throws BeansException if context creation failed
* ps:我们使用的是这个构造方法,加载指定的xml,并自动刷新配置
* 这个方法调用了父类AbstractRefreshableConfigApplicationContext#setConfigLocations方法
* 和AbstractApplicationContext#refresh方法。
* 这两个方法的细节到了对应的类,在细说。
*/
public ClassPathXmlApplicationContext(String configLocation) throws BeansException
this(new String[] configLocation, true, null);
AbstractXmlApplicationContext
所属包:org.springframework.context.support
/**
* Convenient base class for @link org.springframework.context.ApplicationContext
* implementations, drawing configuration from XML documents containing bean definitions
* understood by an @link org.springframework.beans.factory.xml.XmlBeanDefinitionReader.
* 方便的@link org.springframework.context.ApplicationContext实现基类
* 并通过XmlBeanDefinitionReader绘制xml到bean中
* <p>Subclasses just have to implement the @link #getConfigResources and/or
* the @link #getConfigLocations method. Furthermore, they might override
* the @link #getResourceByPath hook to interpret relative paths in an
* environment-specific fashion, and/or @link #getResourcePatternResolver
* for extended pattern resolution.
* 子类必须实现getConfigResources方法。此外,他们也许还需要覆盖getResourceByPath方法
* 去解释相对路径在特殊的环境中,或者覆盖getResourcePatternResolver去扩展解释的模式
* ps:在咱们HelloWorld的demo中,在这个类的逻辑不多
* @author Rod Johnson
* @author Juergen Hoeller
* @see #getConfigResources
* @see #getConfigLocations
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
*/
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext
private boolean validating = true;
/**
* Create a new AbstractXmlApplicationContext with no parent.
*/
public AbstractXmlApplicationContext()
/**
* Create a new AbstractXmlApplicationContext with the given parent context.
* @param parent the parent context
*/
public AbstractXmlApplicationContext(@Nullable ApplicationContext parent)
super(parent);
/**
* Set whether to use XML validation. Default is @code true.
*/
public void setValidating(boolean validating)
this.validating = validating;
/**
* Loads the bean definitions via an XmlBeanDefinitionReader.
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
* @see #initBeanDefinitionReader
* @see #loadBeanDefinitions
*/
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
/**
* Initialize the bean definition reader used for loading the bean
* definitions of this context. Default implementation is empty.
* <p>Can be overridden in subclasses, e.g. for turning off XML validation
* or using a different XmlBeanDefinitionParser implementation.
* @param reader the bean definition reader used by this context
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader#setDocumentReaderClass
*/
protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader)
reader.setValidating(this.validating);
/**
* Load the bean definitions with the given XmlBeanDefinitionReader.
* <p>The lifecycle of the bean factory is handled by the @link #refreshBeanFactory
* method; hence this method is just supposed to load and/or register bean definitions.
* @param reader the XmlBeanDefinitionReader to use
* @throws BeansException in case of bean registration errors
* @throws IOException if the required XML document isn't found
* @see #refreshBeanFactory
* @see #getConfigLocations
* @see #getResources
* @see #getResourcePatternResolver
*/
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException
Resource[] configResources = getConfigResources();
if (configResources != null)
reader.loadBeanDefinitions(configResources);
String[] configLocations = getConfigLocations();
if (configLocations != null)
reader.loadBeanDefinitions(configLocations);
/**
* Return an array of Resource objects, referring to the XML bean definition
* files that this context should be built with.
* <p>The default implementation returns @code null. Subclasses can override
* this to provide pre-built Resource objects rather than location Strings.
* @return an array of Resource objects, or @code null if none
* @see #getConfigLocations()
*/
@Nullable
protected Resource[] getConfigResources()
return null;
AbstractApplicationContext
org.springframework.context.support
/**
* Abstract implementation of the @link org.springframework.context.ApplicationContext
* interface. Doesn't mandate the type of storage used for configuration; simply
* implements common context functionality. Uses the Template Method design pattern,
* requiring concrete subclasses to implement abstract methods.
*
* <p>In contrast to a plain BeanFactory, an ApplicationContext is supposed
* to detect special beans defined in its internal bean factory:
* Therefore, this class automatically registers
* @link org.springframework.beans.factory.config.BeanFactoryPostProcessor BeanFactoryPostProcessors,
* @link org.springframework.beans.factory.config.BeanPostProcessor BeanPostProcessors
* and @link org.springframework.context.ApplicationListener ApplicationListeners
* which are defined as beans in the context.
*
* <p>A @link org.springframework.context.MessageSource may also be supplied
* as a bean in the context, with the name "messageSource"; otherwise, message
* resolution is delegated to the parent context. Furthermore, a multicaster
* for application events can be supplied as "applicationEventMulticaster" bean
* of type @link org.springframework.context.event.ApplicationEventMulticaster
* in the context; otherwise, a default multicaster of type
* @link org.springframework.context.event.SimpleApplicationEventMulticaster will be used.
*
* <p>Implements resource loading through extending
* @link org.springframework.core.io.DefaultResourceLoader.
* Consequently treats non-URL resource paths as class path resources
* (supporting full class path resource names that include the package path,
* e.g. "mypackage/myresource.dat"), unless the @link #getResourceByPath
* method is overwritten in a subclass.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @author Mark Fisher
* @author Stephane Nicoll
* @since January 21, 2001
* @see #refreshBeanFactory
* @see #getBeanFactory
* @see org.springframework.beans.factory.config.BeanFactoryPostProcessor
* @see org.springframework.beans.factory.config.BeanPostProcessor
* @see org.springframework.context.event.ApplicationEventMulticaster
* @see org.springframework.context.ApplicationListener
* @see org.springframework.context.MessageSource
*/
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext
/**
* Name of the MessageSource bean in the factory.
* If none is supplied, message resolution is delegated to the parent.
* @see MessageSource
*/
public static final String MESSAGE_SOURCE_BEAN_NAME = "messageSource";
/**
* Name of the LifecycleProcessor bean in the factory.
* If none is supplied, a DefaultLifecycleProcessor is used.
* @see org.springframework.context.LifecycleProcessor
* @see org.springframework.context.support.DefaultLifecycleProcessor
*/
public static final String LIFECYCLE_PROCESSOR_BEAN_NAME = "lifecycleProcessor";
/**
* Name of the ApplicationEventMulticaster bean in the factory.
* If none is supplied, a default SimpleApplicationEventMulticaster is used.
* @see org.springframework.context.event.ApplicationEventMulticaster
* @see org.springframework.context.event.SimpleApplicationEventMulticaster
*/
public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
static
// Eagerly load the ContextClosedEvent class to avoid weird classloader issues
// on application shutdown in WebLogic 8.1. (Reported by Dustin Woods.)
ContextClosedEvent.class.getName();
/** Logger used by this class. Available to subclasses. */
protected final Log logger = LogFactory.getLog(getClass());
/** Unique id for this context, if any. */
private String id = ObjectUtils.identityToString(this);
/** Display name. */
private String displayName = ObjectUtils.identityToString(this);
/** Parent context. */
@Nullable
private ApplicationContext parent;
/** Environment used by this context. */
@Nullable
private ConfigurableEnvironment environment;
/** BeanFactoryPostProcessors to apply on refresh. */
private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>();
/** System time in milliseconds when this context started. */
private long startupDate;
/** Flag that indicates whether this context is currently active. */
private final AtomicBoolean active = new AtomicBoolean();
/** Flag that indicates whether this context has been closed already. */
private final AtomicBoolean closed = new AtomicBoolean();
/** Synchronization monitor for the "refresh" and "destroy". */
private final Object startupShutdownMonitor = new Object();
/** Reference to the JVM shutdown hook, if registered. */
@Nullable
private Thread shutdownHook;
/** ResourcePatternResolver used by this context. */
private ResourcePatternResolver resourcePatternResolver;
/** LifecycleProcessor for managing the lifecycle of beans within this context. */
@Nullable
private LifecycleProcessor lifecycleProcessor;
/** MessageSource we delegate our implementation of this interface to. */
@Nullable
private MessageSource messageSource;
/** Helper class used in event publishing. */
@Nullable
private ApplicationEventMulticaster applicationEventMulticaster;
/** Statically specified listeners. */
private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
/** ApplicationEvents published early. */
@Nullable
private Set<ApplicationEvent> earlyApplicationEvents;
/**
* Create a new AbstractApplicationContext with no parent.
*/
public AbstractApplicationContext()
this.resourcePatternResolver = getResourcePatternResolver();
/**
* Create a new AbstractApplicationContext with the given parent context.
* @param parent the parent context
*/
public AbstractApplicationContext(@Nullable ApplicationContext parent)
this();
setParent(parent);
//---------------------------------------------------------------------
// Implementation of ApplicationContext interface
//---------------------------------------------------------------------
/**
* Set the unique id of this application context.
* <p>Default is the object id of the context instance, or the name
* of the context bean if the context is itself defined as a bean.
* @param id the unique id of the context
*/
@Override
public void setId(String id)
this.id = id;
@Override
public String getId()
return this.id;
@Override
public String getApplicationName()
return "";
/**
* Set a friendly name for this context.
* Typically done during initialization of concrete context implementations.
* <p>Default is the object id of the context instance.
*/
public void setDisplayName(String displayName)
Assert.hasLength(displayName, "Display name must not be empty");
this.displayName = displayName;
/**
* Return a friendly name for this context.
* @return a display name for this context (never @code null)
*/
@Override
public String getDisplayName()
return this.displayName;
/**
* Return the parent context, or @code null if there is no parent
* (that is, this context is the root of the context hierarchy).
*/
@Override
@Nullable
public ApplicationContext getParent()
return this.parent;
/**
* Set the @code Environment for this application context.
* <p>Default value is determined by @link #createEnvironment(). Replacing the
* default with this method is one option but configuration through @link
* #getEnvironment() should also be considered. In either case, such modifications
* should be performed <em>before</em> @link #refresh().
* @see org.springframework.context.support.AbstractApplicationContext#createEnvironment
*/
@Override
public void setEnvironment(ConfigurableEnvironment environment)
this.environment = environment;
/**
* Return the @code Environment for this application context in configurable
* form, allowing for further customization.
* <p>If none specified, a default environment will be initialized via
* @link #createEnvironment().
*/
@Override
public ConfigurableEnvironment getEnvironment()
if (this.environment == null)
this.environment = createEnvironment();
return this.environment;
/**
* Create and return a new @link StandardEnvironment.
* <p>Subclasses may override this method in order to supply
* a custom @link ConfigurableEnvironment implementation.
*/
protected ConfigurableEnvironment createEnvironment()
return new StandardEnvironment();
/**
* Return this context's internal bean factory as AutowireCapableBeanFactory,
* if already available.
* @see #getBeanFactory()
*/
@Override
public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException
return getBeanFactory();
/**
* Return the timestamp (ms) when this context was first loaded.
*/
@Override
public long getStartupDate()
return this.startupDate;
/**
* Publish the given event to all listeners.
* <p>Note: Listeners get initialized after the MessageSource, to be able
* to access it within listener implementations. Thus, MessageSource
* implementations cannot publish events.
* @param event the event to publish (may be application-specific or a
* standard framework event)
*/
@Override
public void publishEvent(ApplicationEvent event)
publishEvent(event, null);
/**
* Publish the given event to all listeners.
* <p>Note: Listeners get initialized after the MessageSource, to be able
* to access it within listener implementations. Thus, MessageSource
* implementations cannot publish events.
* @param event the event to publish (may be an @link ApplicationEvent
* or a payload object to be turned into a @link PayloadApplicationEvent)
*/
@Override
public void publishEvent(Object event)
publishEvent(event, null);
/**
* Publish the given event to all listeners.
* @param event the event to publish (may be an @link ApplicationEvent
* or a payload object to be turned into a @link PayloadApplicationEvent)
* @param eventType the resolved event type, if known
* @since 4.2
*/
protected void publishEvent(Object event, @Nullable ResolvableType eventType)
Assert.notNull(event, "Event must not be null");
// Decorate event as an ApplicationEvent if necessary
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent)
applicationEvent = (ApplicationEvent) event;
else
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null)
eventType = ((PayloadApplicationEvent) applicationEvent).getResolvableType();
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null)
this.earlyApplicationEvents.add(applicationEvent);
else
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
// Publish event via parent context as well...
if (this.parent != null)
if (this.parent instanceof AbstractApplicationContext)
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
else
this.parent.publishEvent(event);
/**
* Return the internal ApplicationEventMulticaster used by the context.
* @return the internal ApplicationEventMulticaster (never @code null)
* @throws IllegalStateException if the context has not been initialized yet
*/
ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException
if (this.applicationEventMulticaster == null)
throw new IllegalStateException("ApplicationEventMulticaster not initialized - " +
"call 'refresh' before multicasting events via the context: " + this);
return this.applicationEventMulticaster;
/**
* Return the internal LifecycleProcessor used by the context.
* @return the internal LifecycleProcessor (never @code null)
* @throws IllegalStateException if the context has not been initialized yet
*/
LifecycleProcessor getLifecycleProcessor() throws IllegalStateException
if (this.lifecycleProcessor == null)
throw new IllegalStateException("LifecycleProcessor not initialized - " +
"call 'refresh' before invoking lifecycle methods via the context: " + this);
return this.lifecycleProcessor;
/**
* Return the ResourcePatternResolver to use for resolving location patterns
* into Resource instances. Default is a
* @link org.springframework.core.io.support.PathMatchingResourcePatternResolver,
* supporting Ant-style location patterns.
* <p>Can be overridden in subclasses, for extended resolution strategies,
* for example in a web environment.
* <p><b>Do not call this when needing to resolve a location pattern.</b>
* Call the context's @code getResources method instead, which
* will delegate to the ResourcePatternResolver.
* @return the ResourcePatternResolver for this context
* @see #getResources
* @see org.springframework.core.io.support.PathMatchingResourcePatternResolver
*/
protected ResourcePatternResolver getResourcePatternResolver()
return new PathMatchingResourcePatternResolver(this);
//---------------------------------------------------------------------
// Implementation of ConfigurableApplicationContext interface
//---------------------------------------------------------------------
/**
* Set the parent of this application context.
* <p>The parent @linkplain ApplicationContext#getEnvironment() environment is
* @linkplain ConfigurableEnvironment#merge(ConfigurableEnvironment) merged with
* this (child) application context environment if the parent is non-@code null and
* its environment is an instance of @link ConfigurableEnvironment.
* @see ConfigurableEnvironment#merge(ConfigurableEnvironment)
*/
@Override
public void setParent(@Nullable ApplicationContext parent)
this.parent = parent;
if (parent != null)
Environment parentEnvironment = parent.getEnvironment();
if (parentEnvironment instanceof ConfigurableEnvironment)
getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);
@Override
public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor)
Assert.notNull(postProcessor, "BeanFactoryPostProcessor must not be null");
this.beanFactoryPostProcessors.add(postProcessor);
/**
* Return the list of BeanFactoryPostProcessors that will get applied
* to the internal BeanFactory.
*/
public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors()
return this.beanFactoryPostProcessors;
@Override
public void addApplicationListener(ApplicationListener<?> listener)
Assert.notNull(listener, "ApplicationListener must not be null");
if (this.applicationEventMulticaster != null)
this.applicationEventMulticaster.addApplicationListener(listener);
this.applicationListeners.add(listener);
/**
* Return the list of statically specified ApplicationListeners.
*/
public Collection<ApplicationListener<?>> getApplicationListeners()
return this.applicationListeners;
@Override
public void refresh() throws BeansException, IllegalStateException
synchronized (this.startupShutdownMonitor)
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
catch (BeansException ex)
if (logger.isWarnEnabled())
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
finally
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
/**
* Prepare this context for refreshing, setting its startup date and
* active flag as well as performing any initialization of property sources.
*/
protected void prepareRefresh()
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled())
if (logger.isTraceEnabled())
logger.trace("Refreshing " + this);
else
logger.debug("Refreshing " + getDisplayName());
// Initialize any placeholder property sources in the context environment
initPropertySources();
// Validate that all properties marked as required are resolvable
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
/**
* <p>Replace any stub property sources with actual instances.
* @see org.springframework.core.env.PropertySource.StubPropertySource
* @see org.springframework.web.context.support.WebApplicationContextUtils#initServletPropertySources
*/
protected void initPropertySources()
// For subclasses: do nothing by default.
/**
* Tell the subclass to refresh the internal bean factory.
* @return the fresh BeanFactory instance
* @see #refreshBeanFactory()
* @see #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory()
refreshBeanFactory();
return getBeanFactory();
/**
* Configure the factory's standard context characteristics,
* such as the context's ClassLoader and post-processors.
* @param beanFactory the BeanFactory to configure
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory)
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME))
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME))
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME))
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME))
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for registering special
* BeanPostProcessors etc in certain ApplicationContext implementations.
* @param beanFactory the bean factory used by the application context
*/
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
/**
* Instantiate and invoke all registered BeanFactoryPostProcessor beans,
* respecting explicit order if given.
* <p>Must be called before singleton instantiation.
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME))
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
/**
* Instantiate and invoke all registered BeanPostProcessor beans,
* respecting explicit order if given.
* <p>Must be called before any instantiation of application beans.
*/
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory)
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
/**
* Initialize the MessageSource.
* Use parent's if none defined in this context.
*/
protected void initMessageSource()
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME))
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// Make MessageSource aware of parent MessageSource.
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource)
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null)
// Only set parent context as parent MessageSource if no parent MessageSource
// registered already.
hms.setParentMessageSource(getInternalParentMessageSource());
if (logger.isTraceEnabled())
logger.trace("Using MessageSource [" + this.messageSource + "]");
else
// Use empty MessageSource to be able to accept getMessage calls.
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isTraceEnabled())
logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
/**
* Initialize the ApplicationEventMulticaster.
* Uses SimpleApplicationEventMulticaster if none defined in the context.
* @see org.springframework.context.event.SimpleApplicationEventMulticaster
*/
protected void initApplicationEventMulticaster()
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME))
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled())
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
else
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled())
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
/**
* Initialize the LifecycleProcessor.
* Uses DefaultLifecycleProcessor if none defined in the context.
* @see org.springframework.context.support.DefaultLifecycleProcessor
*/
protected void initLifecycleProcessor()
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME))
this.lifecycleProcessor =
beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
if (logger.isTraceEnabled())
logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
else
DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
defaultProcessor.setBeanFactory(beanFactory);
this.lifecycleProcessor = defaultProcessor;
beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
if (logger.isTraceEnabled())
logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +
"[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
/**
* Template method which can be overridden to add context-specific refresh work.
* Called on initialization of special beans, before instantiation of singletons.
* <p>This implementation is empty.
* @throws BeansException in case of errors
* @see #refresh()
*/
protected void onRefresh() throws BeansException
// For subclasses: do nothing by default.
/**
* Add beans that implement ApplicationListener as listeners.
* Doesn't affect other listeners, which can be added without being beans.
*/
protected void registerListeners()
// Register statically specified listeners first.
for (ApplicationListener<?> listener : getApplicationListeners())
getApplicationEventMulticaster().addApplicationListener(listener);
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames)
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
// Publish early application events now that we finally have a multicaster...
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null)
for (ApplicationEvent earlyEvent : earlyEventsToProcess)
getApplicationEventMulticaster().multicastEvent(earlyEvent);
/**
* Finish the initialization of this context's bean factory,
* initializing all remaining singleton beans.
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory)
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class))
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver())
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames)
getBean(weaverAwareName);
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
/**
* Finish the refresh of this context, invoking the LifecycleProcessor's
* onRefresh() method and publishing the
* @link org.springframework.context.event.ContextRefreshedEvent.
*/
protected void finishRefresh()
// Clear context-level resource caches (such as ASM metadata from scanning).
clearResourceCaches();
// Initialize lifecycle processor for this context.
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
/**
* Cancel this context's refresh attempt, resetting the @code active flag
* after an exception got thrown.
* @param ex the exception that led to the cancellation
*/
protected void cancelRefresh(BeansException ex)
this.active.set(false);
/**
* Reset Spring's common reflection metadata caches, in particular the
* @link ReflectionUtils, @link AnnotationUtils, @link ResolvableType
* and @link CachedIntrospectionResults caches.
* @since 4.2
* @see ReflectionUtils#clearCache()
* @see AnnotationUtils#clearCache()
* @see ResolvableType#clearCache()
* @see CachedIntrospectionResults#clearClassLoader(ClassLoader)
*/
protected void resetCommonCaches()
ReflectionUtils.clearCache();
AnnotationUtils.clearCache();
ResolvableType.clearCache();
CachedIntrospectionResults.clearClassLoader(getClassLoader());
/**
* Register a shutdown hook with the JVM runtime, closing this context
* on JVM shutdown unless it has already been closed at that time.
* <p>Delegates to @code doClose() for the actual closing procedure.
* @see Runtime#addShutdownHook
* @see #close()
* @see #doClose()
*/
@Override
public void registerShutdownHook()
if (this.shutdownHook == null)
// No shutdown hook registered yet.
this.shutdownHook = new Thread()
@Override
public void run()
synchronized (startupShutdownMonitor)
doClose();
;
Runtime.getRuntime().addShutdownHook(this.shutdownHook);
/**
* Callback for destruction of this instance, originally attached
* to a @code DisposableBean implementation (not anymore in 5.0).
* <p>The @link #close() method is the native way to shut down
* an ApplicationContext, which this method simply delegates to.
* @deprecated as of Spring Framework 5.0, in favor of @link #close()
*/
@Deprecated
public void destroy()
close();
/**
* Close this application context, destroying all beans in its bean factory.
* <p>Delegates to @code doClose() for the actual closing procedure.
* Also removes a JVM shutdown hook, if registered, as it's not needed anymore.
* @see #doClose()
* @see #registerShutdownHook()
*/
@Override
public void close()
synchronized (this.startupShutdownMonitor)
doClose();
// If we registered a JVM shutdown hook, we don't need it anymore now:
// We've already explicitly closed the context.
if (this.shutdownHook != null)
try
Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
catch (IllegalStateException ex)
// ignore - VM is already shutting down
/**
* Actually performs context closing: publishes a ContextClosedEvent and
* destroys the singletons in the bean factory of this application context.
* <p>Called by both @code close() and a JVM shutdown hook, if any.
* @see org.springframework.context.event.ContextClosedEvent
* @see #destroyBeans()
* @see #close()
* @see #registerShutdownHook()
*/
protected void doClose()
if (this.active.get() && this.closed.compareAndSet(false, true))
if (logger.isDebugEnabled())
logger.debug("Closing " + this);
LiveBeansView.unregisterApplicationContext(this);
try
// Publish shutdown event.
publishEvent(new ContextClosedEvent(this));
catch (Throwable ex)
logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
// Stop all Lifecycle beans, to avoid delays during individual destruction.
if (this.lifecycleProcessor != null)
try
this.lifecycleProcessor.onClose();
catch (Throwable ex)
logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
// Destroy all cached singletons in the context's BeanFactory.
destroyBeans();
// Close the state of this context itself.
closeBeanFactory();
// Let subclasses do some final clean-up if they wish...
onClose();
this.active.set(false);
/**
* Template method for destroying all beans that this context manages.
* The default implementation destroy all cached singletons in this context,
* invoking @code DisposableBean.destroy() and/or the specified
* "destroy-method".
* <p>Can be overridden to add context-specific bean destruction steps
* right before or right after standard singleton destruction,
* while the context's BeanFactory is still active.
* @see #getBeanFactory()
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons()
*/
protected void destroyBeans()
getBeanFactory().destroySingletons();
/**
* Template method which can be overridden to add context-specific shutdown work.
* The default implementation is empty.
* <p>Called at the end of @link #doClose's shutdown procedure, after
* this context's BeanFactory has been closed. If custom shutdown logic
* needs to execute while the BeanFactory is still active, override
* the @link #destroyBeans() method instead.
*/
protected void onClose()
// For subclasses: do nothing by default.
@Override
public boolean isActive()
return this.active.get();
/**
* Assert that this context's BeanFactory is currently active,
* throwing an @link IllegalStateException if it isn't.
* <p>Invoked by all @link BeanFactory delegation methods that depend
* on an active context, i.e. in particular all bean accessor methods.
* <p>The default implementation checks the @link #isActive() 'active' status
* of this context overall. May be overridden for more specific checks, or for a
* no-op if @link #getBeanFactory() itself throws an exception in such a case.
*/
protected void assertBeanFactoryActive()
if (!this.active.get())
if (this.closed.get())
throw new IllegalStateException(getDisplayName() + " has been closed already");
else
throw new IllegalStateException(getDisplayName() + " has not been refreshed yet");
//---------------------------------------------------------------------
// Implementation of BeanFactory interface
//---------------------------------------------------------------------
@Override
public Object getBean(String name) throws BeansException
assertBeanFactoryActive();
return getBeanFactory().getBean(name);
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException
assertBeanFactoryActive();
return getBeanFactory().getBean(name, requiredType);
@Override
public Object getBean(String name, Object... args) throws BeansException
assertBeanFactoryActive();
return getBeanFactory().getBean(name, args);
@Override
public <T> T getBean(Class<T> requiredType) throws BeansException
assertBeanFactoryActive();
return getBeanFactory().getBean(requiredType);
@Override
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException
assertBeanFactoryActive();
return getBeanFactory().getBean(requiredType, args);
@Override
public <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType)
assertBeanFactoryActive();
return getBeanFactory().getBeanProvider(requiredType);
@Override
public <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType)
assertBeanFactoryActive();
return getBeanFactory().getBeanProvider(requiredType);
@Override
public boolean containsBean(String name)
return getBeanFactory().containsBean(name);
@Override
public boolean isSingleton(String name) throws NoSuchBeanDefinitionException
assertBeanFactoryActive();
return getBeanFactory().isSingleton(name);
@Override
public boolean isPrototype(String name) throws NoSuchBeanDefinitionException
assertBeanFactoryActive();
return getBeanFactory().isPrototype(name);
@Override
public boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException
assertBeanFactoryActive();
return getBeanFactory().isTypeMatch(name, typeToMatch);
@Override
public boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException
assertBeanFactoryActive();
return getBeanFactory().isTypeMatch(name, typeToMatch);
@Override
@Nullable
public Class<?> getType(String name) throws NoSuchBeanDefinitionException
assertBeanFactoryActive();
return getBeanFactory().getType(name);
@Override
public String[] getAliases(String name)
return getBeanFactory().getAliases(name);
//---------------------------------------------------------------------
// Implementation of ListableBeanFactory interface
//---------------------------------------------------------------------
@Override
public boolean containsBeanDefinition(String beanName)
return getBeanFactory().containsBeanDefinition(beanName);
@Override
public int getBeanDefinitionCount()
return getBeanFactory().getBeanDefinitionCount();
@Override
public String[] getBeanDefinitionNames()
return getBeanFactory().getBeanDefinitionNames();
@Override
public String[] getBeanNamesForType(ResolvableType type)
assertBeanFactoryActive();
return getBeanFactory().getBeanNamesForType(type);
@Override
public String[] getBeanNamesForType(@Nullable Class<?> type)
assertBeanFactoryActive();
return getBeanFactory().getBeanNamesForType(type);
@Override
public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit)
assertBeanFactoryActive();
return getBeanFactory().getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
@Override
public <T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException
assertBeanFactoryActive();
return getBeanFactory().getBeansOfType(type);
@Override
public <T> Map<String, T> getBeansOfType(@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
throws BeansException
assertBeanFactoryActive();
return getBeanFactory().getBeansOfType(type, includeNonSingletons, allowEagerInit);
@Override
public String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType)
assertBeanFactoryActive();
return getBeanFactory().getBeanNamesForAnnotation(annotationType);
@Override
public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType)
throws BeansException
assertBeanFactoryActive();
return getBeanFactory().getBeansWithAnnotation(annotationType);
@Override
@Nullable
public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
throws NoSuchBeanDefinitionException
assertBeanFactoryActive();
return getBeanFactory().findAnnotationOnBean(beanName, annotationType);
//---------------------------------------------------------------------
// Implementation of HierarchicalBeanFactory interface
//---------------------------------------------------------------------
@Override
@Nullable
public BeanFactory getParentBeanFactory()
return getParent();
@Override
public boolean containsLocalBean(String name)
return getBeanFactory().containsLocalBean(name);
/**
* Return the internal bean factory of the parent context if it implements
* ConfigurableApplicationContext; else, return the parent context itself.
* @see org.springframework.context.ConfigurableApplicationContext#getBeanFactory
*/
@Nullable
protected BeanFactory getInternalParentBeanFactory()
return (getParent() instanceof ConfigurableApplicationContext ?
((ConfigurableApplicationContext) getParent()).getBeanFactory() : getParent());
//---------------------------------------------------------------------
// Implementation of MessageSource interface
//---------------------------------------------------------------------
@Override
public String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale)
return getMessageSource().getMessage(code, args, defaultMessage, locale);
@Override
public String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException
return getMessageSource().getMessage(code, args, locale);
@Override
public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException
return getMessageSource().getMessage(resolvable, locale);
/**
* Return the internal MessageSource used by the context.
* @return the internal MessageSource (never @code null)
* @throws IllegalStateException if the context has not been initialized yet
*/
private MessageSource getMessageSource() throws IllegalStateException
if (this.messageSource == null)
throw new IllegalStateException("MessageSource not initialized - " +
"call 'refresh' before accessing messages via the context: " + this);
return this.messageSource;
/**
* Return the internal message source of the parent context if it is an
* AbstractApplicationContext too; else, return the parent context itself.
*/
@Nullable
protected MessageSource getInternalParentMessageSource()
return (getParent() instanceof AbstractApplicationContext ?
((AbstractApplicationContext) getParent()).messageSource : getParent());
//---------------------------------------------------------------------
// Implementation of ResourcePatternResolver interface
//---------------------------------------------------------------------
@Override
public Resource[] getResources(String locationPattern) throws IOException
return this.resourcePatternResolver.getResources(locationPattern);
//---------------------------------------------------------------------
// Implementation of Lifecycle interface
//---------------------------------------------------------------------
@Override
public void start()
getLifecycleProcessor().start();
publishEvent(new ContextStartedEvent(this));
@Override
public void stop()
getLifecycleProcessor().stop();
publishEvent(new ContextStoppedEvent(this));
@Override
public boolean isRunning()
return (this.lifecycleProcessor != null && this.lifecycleProcessor.isRunning());
//---------------------------------------------------------------------
// Abstract methods that must be implemented by subclasses
//---------------------------------------------------------------------
/**
* Subclasses must implement this method to perform the actual configuration load.
* The method is invoked by @link #refresh() before any other initialization work.
* <p>A subclass will either create a new bean factory and hold a reference to it,
* or return a single BeanFactory instance that it holds. In the latter case, it will
* usually throw an IllegalStateException if refreshing the context more than once.
* @throws BeansException if initialization of the bean factory failed
* @throws IllegalStateException if already initialized and multiple refresh
* attempts are not supported
*/
protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
/**
* Subclasses must implement this method to release their internal bean factory.
* This method gets invoked by @link #close() after all other shutdown work.
* <p>Should never throw an exception but rather log shutdown failures.
*/
protected abstract void closeBeanFactory();
/**
* Subclasses must return their internal bean factory here. They should implement the
* lookup efficiently, so that it can be called repeatedly without a performance penalty.
* <p>Note: Subclasses should check whether the context is still active before
* returning the internal bean factory. The internal factory should generally be
* considered unavailable once the context has been closed.
* @return this application context's internal bean factory (never @code null)
* @throws IllegalStateException if the context does not hold an internal bean factory yet
* (usually if @link #refresh() has never been called) or if the context has been
* closed already
* @see #refreshBeanFactory()
* @see #closeBeanFactory()
*/
@Override
public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
/**
* Return information about this context.
*/
@Override
public String toString()
StringBuilder sb = new StringBuilder(getDisplayName());
sb.append(", started on ").append(new Date(getStartupDate()));
ApplicationContext parent = getParent();
if (parent != null)
sb.append(", parent: ").append(parent.getDisplayName());
return sb.toString();
以上是关于spring源码阅读笔记之HelloWorld和spring第一步ClassPathXMLApplicationContext的主要内容,如果未能解决你的问题,请参考以下文章
spring源码阅读-- 容器启动之BeanFactoryPostProcessor
Spring Boot文档阅读笔记-exception handling–@ExceptionHandler解析与实例
springspring源码阅读之xml读取bean注入(BeanFactory)