📄 abstractapplicationcontext.java
字号:
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 singletons this late to allow them to access the message source.
beanFactory.preInstantiateSingletons();
// Last step: publish corresponding event.
publishEvent(new ContextRefreshedEvent(this));
}
catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.
beanFactory.destroySingletons();
throw ex;
}
}
}
/**
* Prepare this context for refreshing, setting its startup date and
* active flag.
*/
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
synchronized (this.activeMonitor) {
this.active = true;
}
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
}
/**
* Tell the subclass to refresh the internal bean factory.
* @return the fresh BeanFactory instance
* @see #refreshBeanFactory()
* @see #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isInfoEnabled()) {
logger.info("Bean factory for application context [" + ObjectUtils.identityToString(this) +
"]: " + ObjectUtils.identityToString(beanFactory));
}
if (logger.isDebugEnabled()) {
logger.debug(beanFactory.getBeanDefinitionCount() + " beans defined in " + this);
}
return beanFactory;
}
/**
* 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.
beanFactory.setBeanClassLoader(getClassLoader());
// Populate the bean factory with context-specific resource editors.
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this));
// Configure the bean factory with context semantics.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
}
/**
* 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.
* Must be called before singleton instantiation.
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// Invoke factory processors registered with the context instance.
for (Iterator it = getBeanFactoryPostProcessors().iterator(); it.hasNext();) {
BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor) it.next();
factoryProcessor.postProcessBeanFactory(beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] factoryProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement the Ordered
// interface and those that do not.
List orderedFactoryProcessors = new ArrayList();
List nonOrderedFactoryProcessorNames = new ArrayList();
for (int i = 0; i < factoryProcessorNames.length; i++) {
if (isTypeMatch(factoryProcessorNames[i], Ordered.class)) {
orderedFactoryProcessors.add(beanFactory.getBean(factoryProcessorNames[i]));
}
else {
nonOrderedFactoryProcessorNames.add(factoryProcessorNames[i]);
}
}
// First, invoke the BeanFactoryPostProcessors that implement Ordered.
Collections.sort(orderedFactoryProcessors, new OrderComparator());
for (Iterator it = orderedFactoryProcessors.iterator(); it.hasNext();) {
BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor) it.next();
factoryProcessor.postProcessBeanFactory(beanFactory);
}
// Second, invoke all other BeanFactoryPostProcessors, one by one.
for (Iterator it = nonOrderedFactoryProcessorNames.iterator(); it.hasNext();) {
String factoryProcessorName = (String) it.next();
((BeanFactoryPostProcessor) getBean(factoryProcessorName)).postProcessBeanFactory(beanFactory);
}
}
/**
* 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) {
String[] processorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + processorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement the Ordered
// interface and those that do not.
List orderedProcessors = new ArrayList();
List nonOrderedProcessorNames = new ArrayList();
for (int i = 0; i < processorNames.length; i++) {
if (isTypeMatch(processorNames[i], Ordered.class)) {
orderedProcessors.add(getBean(processorNames[i]));
}
else {
nonOrderedProcessorNames.add(processorNames[i]);
}
}
// First, register the BeanPostProcessors that implement Ordered.
Collections.sort(orderedProcessors, new OrderComparator());
for (Iterator it = orderedProcessors.iterator(); it.hasNext();) {
beanFactory.addBeanPostProcessor((BeanPostProcessor) it.next());
}
// Second, register all other BeanPostProcessors, one by one.
for (Iterator it = nonOrderedProcessorNames.iterator(); it.hasNext();) {
String processorName = (String) it.next();
beanFactory.addBeanPostProcessor((BeanPostProcessor) getBean(processorName));
}
}
/**
* Initialize the MessageSource.
* Use parent's if none defined in this context.
*/
protected void initMessageSource() {
if (containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
this.messageSource = (MessageSource) 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.isDebugEnabled()) {
logger.debug("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;
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
"': using default [" + this.messageSource + "]");
}
}
}
/**
* Initialize the ApplicationEventMulticaster.
* Uses SimpleApplicationEventMulticaster if none defined in the context.
* @see org.springframework.context.event.SimpleApplicationEventMulticaster
*/
protected void initApplicationEventMulticaster() {
if (containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster = (ApplicationEventMulticaster)
getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isDebugEnabled()) {
logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster();
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
"': using default [" + this.applicationEventMulticaster + "]");
}
}
}
/**
* 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 (Iterator it = getApplicationListeners().iterator(); it.hasNext();) {
addListener((ApplicationListener) it.next());
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
Collection listenerBeans = getBeansOfType(ApplicationListener.class, true, false).values();
for (Iterator it = listenerBeans.iterator(); it.hasNext();) {
addListener((ApplicationListener) it.next());
}
}
/**
* Subclasses can invoke this method to register a listener.
* Any beans in the context that are listeners are automatically added.
* @param listener the listener to register
*/
protected void addListener(ApplicationListener listener) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
/**
* 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()</code> for the actual closing procedure.
* @see java.lang.Runtime#addShutdownHook
* @see #close()
* @see #doClose()
*/
public void registerShutdownHook() {
if (this.shutdownHook == null) {
// No shutdown hook registered yet.
this.shutdownHook = new Thread() {
public void run() {
doClose();
}
};
Runtime.getRuntime().addShutdownHook(this.shutdownHook);
}
}
/**
* DisposableBean callback for destruction of this instance.
* Only called when the ApplicationContext itself is running
* as a bean in another BeanFactory or ApplicationContext,
* which is rather unusual.
* <p>The <code>close</code> method is the native way to
* shut down an ApplicationContext.
* @see #close()
* @see org.springframework.beans.factory.access.SingletonBeanFactoryLocator
*/
public void destroy() {
close();
}
/**
* Close this application context, destroying all beans in its bean factory.
* <p>Delegates to <code>doClose()</code> for the actual closing procedure.
* Also removes a JVM shutdown hook, if registered, as it's not needed anymore.
* @see #doClose()
* @see #registerShutdownHook()
*/
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) {
Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
}
}
}
/**
* 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()</code> and a JVM shutdown hook, if any.
* @see org.springframework.context.event.ContextClosedEvent
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons()
* @see #close()
* @see #registerShutdownHook()
*/
protected void doClose() {
if (isActive()) {
if (logger.isInfoEnabled()) {
logger.info("Closing " + this);
}
try {
// Publish shutdown event.
publishEvent(new ContextClosedEvent(this));
}
catch (Throwable ex) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -