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