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.beans.factory.support;
018:
019: import java.util.ArrayList;
020: import java.util.HashMap;
021: import java.util.Iterator;
022: import java.util.List;
023: import java.util.Map;
024: import java.util.Set;
025:
026: import org.springframework.beans.BeansException;
027: import org.springframework.beans.factory.BeanCreationException;
028: import org.springframework.beans.factory.BeanFactoryUtils;
029: import org.springframework.beans.factory.BeanIsNotAFactoryException;
030: import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
031: import org.springframework.beans.factory.FactoryBean;
032: import org.springframework.beans.factory.ListableBeanFactory;
033: import org.springframework.beans.factory.NoSuchBeanDefinitionException;
034: import org.springframework.beans.factory.SmartFactoryBean;
035: import org.springframework.util.StringUtils;
036:
037: /**
038: * Static {@link org.springframework.beans.factory.BeanFactory} implementation
039: * which allows to register existing singleton instances programmatically.
040: * Does not have support for prototype beans or aliases.
041: *
042: * <p>Serves as example for a simple implementation of the
043: * {@link org.springframework.beans.factory.ListableBeanFactory} interface,
044: * managing existing bean instances rather than creating new ones based on bean
045: * definitions, and not implementing any extended SPI interfaces (such as
046: * {@link org.springframework.beans.factory.config.ConfigurableBeanFactory}).
047: *
048: * <p>For a full-fledged factory based on bean definitions, have a look
049: * at {@link DefaultListableBeanFactory}.
050: *
051: * @author Rod Johnson
052: * @author Juergen Hoeller
053: * @since 06.01.2003
054: * @see DefaultListableBeanFactory
055: */
056: public class StaticListableBeanFactory implements ListableBeanFactory {
057:
058: /** Map from bean name to bean instance */
059: private final Map beans = new HashMap();
060:
061: /**
062: * Add a new singleton bean.
063: * Will overwrite any existing instance for the given name.
064: * @param name the name of the bean
065: * @param bean the bean instance
066: */
067: public void addBean(String name, Object bean) {
068: this .beans.put(name, bean);
069: }
070:
071: //---------------------------------------------------------------------
072: // Implementation of BeanFactory interface
073: //---------------------------------------------------------------------
074:
075: public Object getBean(String name) throws BeansException {
076: String beanName = BeanFactoryUtils.transformedBeanName(name);
077:
078: Object bean = this .beans.get(beanName);
079: if (bean == null) {
080: throw new NoSuchBeanDefinitionException(
081: beanName,
082: "Defined beans are ["
083: + StringUtils
084: .collectionToCommaDelimitedString(this .beans
085: .keySet()) + "]");
086: }
087:
088: // Don't let calling code try to dereference the
089: // bean factory if the bean isn't a factory
090: if (BeanFactoryUtils.isFactoryDereference(name)
091: && !(bean instanceof FactoryBean)) {
092: throw new BeanIsNotAFactoryException(beanName, bean
093: .getClass());
094: }
095:
096: if (bean instanceof FactoryBean
097: && !BeanFactoryUtils.isFactoryDereference(name)) {
098: try {
099: return ((FactoryBean) bean).getObject();
100: } catch (Exception ex) {
101: throw new BeanCreationException(
102: beanName,
103: "FactoryBean threw exception on object creation",
104: ex);
105: }
106: }
107: return bean;
108: }
109:
110: public Object getBean(String name, Class requiredType)
111: throws BeansException {
112: Object bean = getBean(name);
113: if (requiredType != null
114: && !requiredType.isAssignableFrom(bean.getClass())) {
115: throw new BeanNotOfRequiredTypeException(name,
116: requiredType, bean.getClass());
117: }
118: return bean;
119: }
120:
121: public boolean containsBean(String name) {
122: return this .beans.containsKey(name);
123: }
124:
125: public boolean isSingleton(String name)
126: throws NoSuchBeanDefinitionException {
127: Object bean = getBean(name);
128: // In case of FactoryBean, return singleton status of created object.
129: return (bean instanceof FactoryBean && ((FactoryBean) bean)
130: .isSingleton());
131: }
132:
133: public boolean isPrototype(String name)
134: throws NoSuchBeanDefinitionException {
135: Object bean = getBean(name);
136: // In case of FactoryBean, return prototype status of created object.
137: return ((bean instanceof SmartFactoryBean && ((SmartFactoryBean) bean)
138: .isPrototype()) || (bean instanceof FactoryBean && !((FactoryBean) bean)
139: .isSingleton()));
140: }
141:
142: public boolean isTypeMatch(String name, Class targetType)
143: throws NoSuchBeanDefinitionException {
144: Class type = getType(name);
145: return (targetType == null || (type != null && targetType
146: .isAssignableFrom(type)));
147: }
148:
149: public Class getType(String name)
150: throws NoSuchBeanDefinitionException {
151: String beanName = BeanFactoryUtils.transformedBeanName(name);
152:
153: Object bean = this .beans.get(beanName);
154: if (bean == null) {
155: throw new NoSuchBeanDefinitionException(
156: beanName,
157: "Defined beans are ["
158: + StringUtils
159: .collectionToCommaDelimitedString(this .beans
160: .keySet()) + "]");
161: }
162:
163: if (bean instanceof FactoryBean
164: && !BeanFactoryUtils.isFactoryDereference(name)) {
165: // If it's a FactoryBean, we want to look at what it creates, not the factory class.
166: return ((FactoryBean) bean).getObjectType();
167: }
168: return bean.getClass();
169: }
170:
171: public String[] getAliases(String name) {
172: return new String[0];
173: }
174:
175: //---------------------------------------------------------------------
176: // Implementation of ListableBeanFactory interface
177: //---------------------------------------------------------------------
178:
179: public boolean containsBeanDefinition(String name) {
180: return this .beans.containsKey(name);
181: }
182:
183: public int getBeanDefinitionCount() {
184: return this .beans.size();
185: }
186:
187: public String[] getBeanDefinitionNames() {
188: return StringUtils.toStringArray(this .beans.keySet());
189: }
190:
191: public String[] getBeanNamesForType(Class type) {
192: return getBeanNamesForType(type, true, true);
193: }
194:
195: public String[] getBeanNamesForType(Class type,
196: boolean includePrototypes, boolean includeFactoryBeans) {
197: boolean isFactoryType = (type != null && FactoryBean.class
198: .isAssignableFrom(type));
199: List matches = new ArrayList();
200: Set keys = this .beans.keySet();
201: Iterator it = keys.iterator();
202: while (it.hasNext()) {
203: String name = (String) it.next();
204: Object beanInstance = this .beans.get(name);
205: if (beanInstance instanceof FactoryBean && !isFactoryType) {
206: if (includeFactoryBeans) {
207: Class objectType = ((FactoryBean) beanInstance)
208: .getObjectType();
209: if (objectType != null
210: && type.isAssignableFrom(objectType)) {
211: matches.add(name);
212: }
213: }
214: } else {
215: if (type.isInstance(beanInstance)) {
216: matches.add(name);
217: }
218: }
219: }
220: return StringUtils.toStringArray(matches);
221: }
222:
223: public Map getBeansOfType(Class type) throws BeansException {
224: return getBeansOfType(type, true, true);
225: }
226:
227: public Map getBeansOfType(Class type, boolean includePrototypes,
228: boolean includeFactoryBeans) throws BeansException {
229:
230: boolean isFactoryType = (type != null && FactoryBean.class
231: .isAssignableFrom(type));
232: Map matches = new HashMap();
233:
234: Iterator it = this .beans.entrySet().iterator();
235: while (it.hasNext()) {
236: Map.Entry entry = (Map.Entry) it.next();
237: String beanName = (String) entry.getKey();
238: Object beanInstance = entry.getValue();
239:
240: // Is bean a FactoryBean?
241: if (beanInstance instanceof FactoryBean && !isFactoryType) {
242: if (includeFactoryBeans) {
243: // Match object created by FactoryBean.
244: FactoryBean factory = (FactoryBean) beanInstance;
245: Class objectType = factory.getObjectType();
246: if ((includePrototypes || factory.isSingleton())
247: && objectType != null
248: && type.isAssignableFrom(objectType)) {
249: matches.put(beanName, getBean(beanName));
250: }
251: }
252: } else {
253: if (type.isInstance(beanInstance)) {
254: // If type to match is FactoryBean, return FactoryBean itself.
255: // Else, return bean instance.
256: if (isFactoryType) {
257: beanName = FACTORY_BEAN_PREFIX + beanName;
258: }
259: matches.put(beanName, beanInstance);
260: }
261: }
262: }
263: return matches;
264: }
265:
266: }
|