/*
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.support;
import java.io.IOException;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextException;
import org.springframework.lang.Nullable;
Base class for ApplicationContext
implementations which are supposed to support multiple calls to AbstractApplicationContext.refresh()
, creating a new internal bean factory instance every time. Typically (but not necessarily), such a context will be driven by a set of config locations to load bean definitions from. The only method to be implemented by subclasses is loadBeanDefinitions
, which gets invoked on each refresh. A concrete implementation is supposed to load bean definitions into the given DefaultListableBeanFactory
, typically delegating to one or more specific bean definition readers.
Note that there is a similar base class for WebApplicationContexts. AbstractRefreshableWebApplicationContext
provides the same subclassing strategy, but additionally pre-implements all context functionality for web environments. There is also a pre-defined way to receive config locations for a web context.
Concrete standalone subclasses of this base class, reading in a specific bean definition format, are ClassPathXmlApplicationContext
and FileSystemXmlApplicationContext
, which both derive from the common AbstractXmlApplicationContext
base class; AnnotationConfigApplicationContext
supports @Configuration
-annotated classes as a source of bean definitions.
Author: Juergen Hoeller, Chris Beams See Also: Since: 1.1.3
/**
* Base class for {@link org.springframework.context.ApplicationContext}
* implementations which are supposed to support multiple calls to {@link #refresh()},
* creating a new internal bean factory instance every time.
* Typically (but not necessarily), such a context will be driven by
* a set of config locations to load bean definitions from.
*
* <p>The only method to be implemented by subclasses is {@link #loadBeanDefinitions},
* which gets invoked on each refresh. A concrete implementation is supposed to load
* bean definitions into the given
* {@link org.springframework.beans.factory.support.DefaultListableBeanFactory},
* typically delegating to one or more specific bean definition readers.
*
* <p><b>Note that there is a similar base class for WebApplicationContexts.</b>
* {@link org.springframework.web.context.support.AbstractRefreshableWebApplicationContext}
* provides the same subclassing strategy, but additionally pre-implements
* all context functionality for web environments. There is also a
* pre-defined way to receive config locations for a web context.
*
* <p>Concrete standalone subclasses of this base class, reading in a
* specific bean definition format, are {@link ClassPathXmlApplicationContext}
* and {@link FileSystemXmlApplicationContext}, which both derive from the
* common {@link AbstractXmlApplicationContext} base class;
* {@link org.springframework.context.annotation.AnnotationConfigApplicationContext}
* supports {@code @Configuration}-annotated classes as a source of bean definitions.
*
* @author Juergen Hoeller
* @author Chris Beams
* @since 1.1.3
* @see #loadBeanDefinitions
* @see org.springframework.beans.factory.support.DefaultListableBeanFactory
* @see org.springframework.web.context.support.AbstractRefreshableWebApplicationContext
* @see AbstractXmlApplicationContext
* @see ClassPathXmlApplicationContext
* @see FileSystemXmlApplicationContext
* @see org.springframework.context.annotation.AnnotationConfigApplicationContext
*/
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
@Nullable
private Boolean allowBeanDefinitionOverriding;
@Nullable
private Boolean allowCircularReferences;
Bean factory for this context. /** Bean factory for this context. */
@Nullable
private DefaultListableBeanFactory beanFactory;
Synchronization monitor for the internal BeanFactory. /** Synchronization monitor for the internal BeanFactory. */
private final Object beanFactoryMonitor = new Object();
Create a new AbstractRefreshableApplicationContext with no parent.
/**
* Create a new AbstractRefreshableApplicationContext with no parent.
*/
public AbstractRefreshableApplicationContext() {
}
Create a new AbstractRefreshableApplicationContext with the given parent context.
Params: - parent – the parent context
/**
* Create a new AbstractRefreshableApplicationContext with the given parent context.
* @param parent the parent context
*/
public AbstractRefreshableApplicationContext(@Nullable ApplicationContext parent) {
super(parent);
}
Set whether it should be allowed to override bean definitions by registering
a different definition with the same name, automatically replacing the former.
If not, an exception will be thrown. Default is "true".
See Also: - setAllowBeanDefinitionOverriding.setAllowBeanDefinitionOverriding
/**
* Set whether it should be allowed to override bean definitions by registering
* a different definition with the same name, automatically replacing the former.
* If not, an exception will be thrown. Default is "true".
* @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowBeanDefinitionOverriding
*/
public void setAllowBeanDefinitionOverriding(boolean allowBeanDefinitionOverriding) {
this.allowBeanDefinitionOverriding = allowBeanDefinitionOverriding;
}
Set whether to allow circular references between beans - and automatically
try to resolve them.
Default is "true". Turn this off to throw an exception when encountering
a circular reference, disallowing them completely.
See Also: - setAllowCircularReferences.setAllowCircularReferences
/**
* Set whether to allow circular references between beans - and automatically
* try to resolve them.
* <p>Default is "true". Turn this off to throw an exception when encountering
* a circular reference, disallowing them completely.
* @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowCircularReferences
*/
public void setAllowCircularReferences(boolean allowCircularReferences) {
this.allowCircularReferences = allowCircularReferences;
}
This implementation performs an actual refresh of this context's underlying
bean factory, shutting down the previous bean factory (if any) and
initializing a fresh bean factory for the next phase of the context's lifecycle.
/**
* This implementation performs an actual refresh of this context's underlying
* bean factory, shutting down the previous bean factory (if any) and
* initializing a fresh bean factory for the next phase of the context's lifecycle.
*/
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
@Override
protected void cancelRefresh(BeansException ex) {
synchronized (this.beanFactoryMonitor) {
if (this.beanFactory != null) {
this.beanFactory.setSerializationId(null);
}
}
super.cancelRefresh(ex);
}
@Override
protected final void closeBeanFactory() {
synchronized (this.beanFactoryMonitor) {
if (this.beanFactory != null) {
this.beanFactory.setSerializationId(null);
this.beanFactory = null;
}
}
}
Determine whether this context currently holds a bean factory,
i.e. has been refreshed at least once and not been closed yet.
/**
* Determine whether this context currently holds a bean factory,
* i.e. has been refreshed at least once and not been closed yet.
*/
protected final boolean hasBeanFactory() {
synchronized (this.beanFactoryMonitor) {
return (this.beanFactory != null);
}
}
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
synchronized (this.beanFactoryMonitor) {
if (this.beanFactory == null) {
throw new IllegalStateException("BeanFactory not initialized or already closed - " +
"call 'refresh' before accessing beans via the ApplicationContext");
}
return this.beanFactory;
}
}
Overridden to turn it into a no-op: With AbstractRefreshableApplicationContext, getBeanFactory()
serves a strong assertion for an active context anyway. /**
* Overridden to turn it into a no-op: With AbstractRefreshableApplicationContext,
* {@link #getBeanFactory()} serves a strong assertion for an active context anyway.
*/
@Override
protected void assertBeanFactoryActive() {
}
Create an internal bean factory for this context. Called for each AbstractApplicationContext.refresh()
attempt. The default implementation creates a DefaultListableBeanFactory
with the internal bean factory of this context's parent as parent bean factory. Can be overridden in subclasses, for example to customize DefaultListableBeanFactory's settings.
See Also: Returns: the bean factory for this context
/**
* Create an internal bean factory for this context.
* Called for each {@link #refresh()} attempt.
* <p>The default implementation creates a
* {@link org.springframework.beans.factory.support.DefaultListableBeanFactory}
* with the {@linkplain #getInternalParentBeanFactory() internal bean factory} of this
* context's parent as parent bean factory. Can be overridden in subclasses,
* for example to customize DefaultListableBeanFactory's settings.
* @return the bean factory for this context
* @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowBeanDefinitionOverriding
* @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowEagerClassLoading
* @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowCircularReferences
* @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowRawInjectionDespiteWrapping
*/
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
Customize the internal bean factory used by this context. Called for each AbstractApplicationContext.refresh()
attempt. The default implementation applies this context's "allowBeanDefinitionOverriding" and "allowCircularReferences" settings, if specified. Can be overridden in subclasses to customize any of DefaultListableBeanFactory
's settings.
Params: - beanFactory – the newly created bean factory for this context
See Also:
/**
* Customize the internal bean factory used by this context.
* Called for each {@link #refresh()} attempt.
* <p>The default implementation applies this context's
* {@linkplain #setAllowBeanDefinitionOverriding "allowBeanDefinitionOverriding"}
* and {@linkplain #setAllowCircularReferences "allowCircularReferences"} settings,
* if specified. Can be overridden in subclasses to customize any of
* {@link DefaultListableBeanFactory}'s settings.
* @param beanFactory the newly created bean factory for this context
* @see DefaultListableBeanFactory#setAllowBeanDefinitionOverriding
* @see DefaultListableBeanFactory#setAllowCircularReferences
* @see DefaultListableBeanFactory#setAllowRawInjectionDespiteWrapping
* @see DefaultListableBeanFactory#setAllowEagerClassLoading
*/
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
if (this.allowBeanDefinitionOverriding != null) {
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.allowCircularReferences != null) {
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}
Load bean definitions into the given bean factory, typically through
delegating to one or more bean definition readers.
Params: - beanFactory – the bean factory to load bean definitions into
Throws: - BeansException – if parsing of the bean definitions failed
- IOException – if loading of bean definition files failed
See Also:
/**
* Load bean definitions into the given bean factory, typically through
* delegating to one or more bean definition readers.
* @param beanFactory the bean factory to load bean definitions into
* @throws BeansException if parsing of the bean definitions failed
* @throws IOException if loading of bean definition files failed
* @see org.springframework.beans.factory.support.PropertiesBeanDefinitionReader
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
*/
protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
throws BeansException, IOException;
}