001: /*
002: * Copyright 2002-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.context.support;
018:
019: import java.io.IOException;
020:
021: import org.springframework.beans.BeansException;
022: import org.springframework.beans.factory.config.BeanDefinition;
023: import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
024: import org.springframework.beans.factory.support.BeanDefinitionRegistry;
025: import org.springframework.beans.factory.support.DefaultListableBeanFactory;
026: import org.springframework.context.ApplicationContext;
027: import org.springframework.core.io.Resource;
028: import org.springframework.core.io.ResourceLoader;
029: import org.springframework.core.io.support.ResourcePatternResolver;
030: import org.springframework.util.Assert;
031:
032: /**
033: * Generic ApplicationContext implementation that holds a single internal
034: * {@link org.springframework.beans.factory.support.DefaultListableBeanFactory}
035: * instance and does not assume a specific bean definition format. Implements
036: * the {@link org.springframework.beans.factory.support.BeanDefinitionRegistry}
037: * interface in order to allow for applying any bean definition readers to it.
038: *
039: * <p>Typical usage is to register a variety of bean definitions via the
040: * {@link org.springframework.beans.factory.support.BeanDefinitionRegistry}
041: * interface and then call {@link #refresh()} to initialize those beans
042: * with application context semantics (handling
043: * {@link org.springframework.context.ApplicationContextAware}, auto-detecting
044: * {@link org.springframework.beans.factory.config.BeanFactoryPostProcessor BeanFactoryPostProcessors},
045: * etc).
046: *
047: * <p>In contrast to other ApplicationContext implementations that create a new
048: * internal BeanFactory instance for each refresh, the internal BeanFactory of
049: * this context is available right from the start, to be able to register bean
050: * definitions on it. {@link #refresh()} may only be called once.
051: *
052: * <p>Usage example:
053: *
054: * <pre>
055: * GenericApplicationContext ctx = new GenericApplicationContext();
056: * XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
057: * xmlReader.loadBeanDefinitions(new ClassPathResource("applicationContext.xml"));
058: * PropertiesBeanDefinitionReader propReader = new PropertiesBeanDefinitionReader(ctx);
059: * propReader.loadBeanDefinitions(new ClassPathResource("otherBeans.properties"));
060: * ctx.refresh();
061: *
062: * MyBean myBean = (MyBean) ctx.getBean("myBean");
063: * ...</pre>
064: *
065: * For the typical case of XML bean definitions, simply use
066: * {@link ClassPathXmlApplicationContext} or {@link FileSystemXmlApplicationContext},
067: * which are easier to set up - but less flexible, since you can just use standard
068: * resource locations for XML bean definitions, rather than mixing arbitrary bean
069: * definition formats. The equivalent in a web environment is
070: * {@link org.springframework.web.context.support.XmlWebApplicationContext}.
071: *
072: * <p>For custom application context implementations that are supposed to read
073: * special bean definition formats in a refreshable manner, consider deriving
074: * from the {@link AbstractRefreshableApplicationContext} base class.
075: *
076: * @author Juergen Hoeller
077: * @since 1.1.2
078: * @see #registerBeanDefinition
079: * @see #refresh()
080: * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
081: * @see org.springframework.beans.factory.support.PropertiesBeanDefinitionReader
082: */
083: public class GenericApplicationContext extends
084: AbstractApplicationContext implements BeanDefinitionRegistry {
085:
086: private final DefaultListableBeanFactory beanFactory;
087:
088: private ResourceLoader resourceLoader;
089:
090: private boolean refreshed = false;
091:
092: /**
093: * Create a new GenericApplicationContext.
094: * @see #registerBeanDefinition
095: * @see #refresh
096: */
097: public GenericApplicationContext() {
098: this .beanFactory = new DefaultListableBeanFactory();
099: }
100:
101: /**
102: * Create a new GenericApplicationContext with the given DefaultListableBeanFactory.
103: * @param beanFactory the DefaultListableBeanFactory instance to use for this context
104: * @see #registerBeanDefinition
105: * @see #refresh
106: */
107: public GenericApplicationContext(
108: DefaultListableBeanFactory beanFactory) {
109: Assert.notNull(beanFactory, "BeanFactory must not be null");
110: this .beanFactory = beanFactory;
111: }
112:
113: /**
114: * Create a new GenericApplicationContext with the given parent.
115: * @param parent the parent application context
116: * @see #registerBeanDefinition
117: * @see #refresh
118: */
119: public GenericApplicationContext(ApplicationContext parent) {
120: this ();
121: setParent(parent);
122: }
123:
124: /**
125: * Create a new GenericApplicationContext with the given DefaultListableBeanFactory.
126: * @param beanFactory the DefaultListableBeanFactory instance to use for this context
127: * @param parent the parent application context
128: * @see #registerBeanDefinition
129: * @see #refresh
130: */
131: public GenericApplicationContext(
132: DefaultListableBeanFactory beanFactory,
133: ApplicationContext parent) {
134: this (beanFactory);
135: setParent(parent);
136: }
137:
138: /**
139: * Set the parent of this application context, also setting
140: * the parent of the internal BeanFactory accordingly.
141: * @see org.springframework.beans.factory.config.ConfigurableBeanFactory#setParentBeanFactory
142: */
143: public void setParent(ApplicationContext parent) {
144: super .setParent(parent);
145: this .beanFactory
146: .setParentBeanFactory(getInternalParentBeanFactory());
147: }
148:
149: /**
150: * Set a ResourceLoader to use for this context. If set, the context will
151: * delegate all <code>getResource</code> calls to the given ResourceLoader.
152: * If not set, default resource loading will apply.
153: * <p>The main reason to specify a custom ResourceLoader is to resolve
154: * resource paths (withour URL prefix) in a specific fashion.
155: * The default behavior is to resolve such paths as class path locations.
156: * To resolve resource paths as file system locations, specify a
157: * FileSystemResourceLoader here.
158: * <p>You can also pass in a full ResourcePatternResolver, which will
159: * be autodetected by the context and used for <code>getResources</code>
160: * calls as well. Else, default resource pattern matching will apply.
161: * @see #getResource
162: * @see org.springframework.core.io.DefaultResourceLoader
163: * @see org.springframework.core.io.FileSystemResourceLoader
164: * @see org.springframework.core.io.support.ResourcePatternResolver
165: * @see #getResources
166: */
167: public void setResourceLoader(ResourceLoader resourceLoader) {
168: this .resourceLoader = resourceLoader;
169: }
170:
171: /**
172: * This implementation delegates to this context's ResourceLoader if set,
173: * falling back to the default superclass behavior else.
174: * @see #setResourceLoader
175: */
176: public Resource getResource(String location) {
177: if (this .resourceLoader != null) {
178: return this .resourceLoader.getResource(location);
179: }
180: return super .getResource(location);
181: }
182:
183: /**
184: * This implementation delegates to this context's ResourceLoader if it
185: * implements the ResourcePatternResolver interface, falling back to the
186: * default superclass behavior else.
187: * @see #setResourceLoader
188: */
189: public Resource[] getResources(String locationPattern)
190: throws IOException {
191: if (this .resourceLoader instanceof ResourcePatternResolver) {
192: return ((ResourcePatternResolver) this .resourceLoader)
193: .getResources(locationPattern);
194: }
195: return super .getResources(locationPattern);
196: }
197:
198: //---------------------------------------------------------------------
199: // Implementations of AbstractApplicationContext's template methods
200: //---------------------------------------------------------------------
201:
202: /**
203: * Do nothing: We hold a single internal BeanFactory and rely on callers
204: * to register beans through our public methods (or the BeanFactory's).
205: * @see #registerBeanDefinition
206: */
207: protected final void refreshBeanFactory()
208: throws IllegalStateException {
209: if (this .refreshed) {
210: throw new IllegalStateException(
211: "GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
212: }
213: this .refreshed = true;
214: }
215:
216: /**
217: * Do nothing: We hold a single internal BeanFactory that will never
218: * get released.
219: */
220: protected final void closeBeanFactory() {
221: }
222:
223: /**
224: * Return the single internal BeanFactory held by this context
225: * (as ConfigurableListableBeanFactory).
226: */
227: public final ConfigurableListableBeanFactory getBeanFactory() {
228: return this .beanFactory;
229: }
230:
231: /**
232: * Return the underlying bean factory of this context,
233: * available for registering bean definitions.
234: * <p><b>NOTE:</b> You need to call {@link #refresh()} to initialize the
235: * bean factory and its contained beans with application context semantics
236: * (autodetecting BeanFactoryPostProcessors, etc).
237: * @return the internal bean factory (as DefaultListableBeanFactory)
238: */
239: public final DefaultListableBeanFactory getDefaultListableBeanFactory() {
240: return this .beanFactory;
241: }
242:
243: //---------------------------------------------------------------------
244: // Implementation of BeanDefinitionRegistry
245: //---------------------------------------------------------------------
246:
247: public BeanDefinition getBeanDefinition(String beanName)
248: throws BeansException {
249: return this .beanFactory.getBeanDefinition(beanName);
250: }
251:
252: public void registerBeanDefinition(String beanName,
253: BeanDefinition beanDefinition) throws BeansException {
254: this .beanFactory.registerBeanDefinition(beanName,
255: beanDefinition);
256: }
257:
258: public void registerAlias(String beanName, String alias)
259: throws BeansException {
260: this.beanFactory.registerAlias(beanName, alias);
261: }
262:
263: }
|