Source Code Cross Referenced for DefaultSingletonBeanRegistry.java in  » J2EE » spring-framework-2.5 » org » springframework » beans » factory » support » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » spring framework 2.5 » org.springframework.beans.factory.support 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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.Collections;
020:        import java.util.HashSet;
021:        import java.util.Iterator;
022:        import java.util.LinkedHashSet;
023:        import java.util.LinkedList;
024:        import java.util.List;
025:        import java.util.Map;
026:        import java.util.Set;
027:        import java.util.LinkedHashMap;
028:
029:        import org.apache.commons.logging.Log;
030:        import org.apache.commons.logging.LogFactory;
031:
032:        import org.springframework.beans.factory.BeanCreationException;
033:        import org.springframework.beans.factory.BeanCreationNotAllowedException;
034:        import org.springframework.beans.factory.BeanCurrentlyInCreationException;
035:        import org.springframework.beans.factory.DisposableBean;
036:        import org.springframework.beans.factory.ObjectFactory;
037:        import org.springframework.beans.factory.config.SingletonBeanRegistry;
038:        import org.springframework.core.CollectionFactory;
039:        import org.springframework.util.Assert;
040:        import org.springframework.util.StringUtils;
041:
042:        /**
043:         * Generic registry for shared bean instances, implementing the
044:         * {@link org.springframework.beans.factory.config.SingletonBeanRegistry}.
045:         * Allows for registering singleton instances that should be shared
046:         * for all callers of the registry, to be obtained via bean name.
047:         *
048:         * <p>Also supports registration of
049:         * {@link org.springframework.beans.factory.DisposableBean} instances,
050:         * (which might or might not correspond to registered singletons),
051:         * to be destroyed on shutdown of the registry. Dependencies between
052:         * beans can be registered to enforce an appropriate shutdown order.
053:         *
054:         * <p>This class mainly serves as base class for
055:         * {@link org.springframework.beans.factory.BeanFactory} implementations,
056:         * factoring out the common management of singleton bean instances. Note that
057:         * the {@link org.springframework.beans.factory.config.ConfigurableBeanFactory}
058:         * interface extends the {@link SingletonBeanRegistry} interface.
059:         *
060:         * <p>Note that this class assumes neither a bean definition concept
061:         * nor a specific creation process for bean instances, in contrast to
062:         * {@link AbstractBeanFactory} and {@link DefaultListableBeanFactory}
063:         * (which inherit from it). Can alternatively also be used as a nested
064:         * helper to delegate to.
065:         *
066:         * @author Juergen Hoeller
067:         * @since 2.0
068:         * @see #registerSingleton
069:         * @see #registerDisposableBean
070:         * @see org.springframework.beans.factory.DisposableBean
071:         * @see org.springframework.beans.factory.config.ConfigurableBeanFactory
072:         */
073:        public class DefaultSingletonBeanRegistry implements 
074:                SingletonBeanRegistry {
075:
076:            /**
077:             * Internal marker for a null singleton object:
078:             * used as marker value for concurrent Maps (which don't support null values).
079:             */
080:            private static final Object NULL_OBJECT = new Object();
081:
082:            /** Logger available to subclasses */
083:            protected final Log logger = LogFactory.getLog(getClass());
084:
085:            /** Cache of singleton objects: bean name --> bean instance */
086:            private final Map singletonObjects = CollectionFactory
087:                    .createConcurrentMapIfPossible(16);
088:
089:            /** Set of registered singletons, containing the bean names in registration order */
090:            private final Set registeredSingletons = new LinkedHashSet(16);
091:
092:            /** Names of beans that are currently in creation */
093:            private final Set singletonsCurrentlyInCreation = Collections
094:                    .synchronizedSet(new HashSet());
095:
096:            /** List of suppressed Exceptions, available for associating related causes */
097:            private List suppressedExceptions;
098:
099:            /** Flag that indicates whether we're currently within destroySingletons */
100:            private boolean singletonsCurrentlyInDestruction = false;
101:
102:            /** Disposable bean instances: bean name --> disposable instance */
103:            private final Map disposableBeans = new LinkedHashMap(16);
104:
105:            /** Map between dependent bean names: bean name --> Set of dependent bean names */
106:            private final Map dependentBeanMap = CollectionFactory
107:                    .createConcurrentMapIfPossible(16);
108:
109:            /** Map between depending bean names: bean name --> Set of bean names for the bean's dependencies */
110:            private final Map dependenciesForBeanMap = CollectionFactory
111:                    .createConcurrentMapIfPossible(16);
112:
113:            public void registerSingleton(String beanName,
114:                    Object singletonObject) throws IllegalStateException {
115:                Assert.notNull(beanName, "'beanName' must not be null");
116:                synchronized (this .singletonObjects) {
117:                    Object oldObject = this .singletonObjects.get(beanName);
118:                    if (oldObject != null) {
119:                        throw new IllegalStateException(
120:                                "Could not register object [" + singletonObject
121:                                        + "] under bean name '" + beanName
122:                                        + "': there is already object ["
123:                                        + oldObject + "] bound");
124:                    }
125:                    addSingleton(beanName, singletonObject);
126:                }
127:            }
128:
129:            /**
130:             * Add the given singleton object to the singleton cache of this factory.
131:             * <p>To be called for eager registration of singletons, e.g. to be able to
132:             * resolve circular references.
133:             * @param beanName the name of the bean
134:             * @param singletonObject the singleton object
135:             */
136:            protected void addSingleton(String beanName, Object singletonObject) {
137:                synchronized (this .singletonObjects) {
138:                    this .singletonObjects.put(beanName,
139:                            (singletonObject != null ? singletonObject
140:                                    : NULL_OBJECT));
141:                    this .registeredSingletons.add(beanName);
142:                }
143:            }
144:
145:            public Object getSingleton(String beanName) {
146:                Object singletonObject = this .singletonObjects.get(beanName);
147:                return (singletonObject != NULL_OBJECT ? singletonObject : null);
148:            }
149:
150:            /**
151:             * Return the (raw) singleton object registered under the given name,
152:             * creating and registering a new one if none registered yet.
153:             * @param beanName the name of the bean
154:             * @param singletonFactory the ObjectFactory to lazily create the singleton
155:             * with, if necessary
156:             * @return the registered singleton object
157:             */
158:            public Object getSingleton(String beanName,
159:                    ObjectFactory singletonFactory) {
160:                Assert.notNull(beanName, "'beanName' must not be null");
161:                synchronized (this .singletonObjects) {
162:                    // Re-check singleton cache within synchronized block.
163:                    Object singletonObject = this .singletonObjects
164:                            .get(beanName);
165:                    if (singletonObject == null) {
166:                        if (this .singletonsCurrentlyInDestruction) {
167:                            throw new BeanCreationNotAllowedException(
168:                                    beanName,
169:                                    "Singleton bean creation not allowed while the singletons of this factory are in destruction "
170:                                            + "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
171:                        }
172:                        if (logger.isDebugEnabled()) {
173:                            logger
174:                                    .debug("Creating shared instance of singleton bean '"
175:                                            + beanName + "'");
176:                        }
177:                        beforeSingletonCreation(beanName);
178:                        boolean recordSuppressedExceptions = (this .suppressedExceptions == null);
179:                        if (recordSuppressedExceptions) {
180:                            this .suppressedExceptions = new LinkedList();
181:                        }
182:                        try {
183:                            singletonObject = singletonFactory.getObject();
184:                        } catch (BeanCreationException ex) {
185:                            for (Iterator it = this .suppressedExceptions
186:                                    .iterator(); it.hasNext();) {
187:                                ex.addRelatedCause((Exception) it.next());
188:                            }
189:                            throw ex;
190:                        } finally {
191:                            if (recordSuppressedExceptions) {
192:                                this .suppressedExceptions = null;
193:                            }
194:                            afterSingletonCreation(beanName);
195:                        }
196:                        addSingleton(beanName, singletonObject);
197:                    }
198:                    return (singletonObject != NULL_OBJECT ? singletonObject
199:                            : null);
200:                }
201:            }
202:
203:            /**
204:             * Register an Exception that happened to get suppressed during the creation of a
205:             * singleton bean instance, e.g. a temporary circular reference resolution problem.
206:             * @param ex the Exception to register
207:             */
208:            protected void onSuppressedException(Exception ex) {
209:                synchronized (this .singletonObjects) {
210:                    if (this .suppressedExceptions != null) {
211:                        this .suppressedExceptions.add(ex);
212:                    }
213:                }
214:            }
215:
216:            /**
217:             * Remove the bean with the given name from the singleton cache of this factory.
218:             * <p>To be able to clean up eager registration of a singleton if creation failed.
219:             * @param beanName the name of the bean
220:             */
221:            protected void removeSingleton(String beanName) {
222:                this .singletonObjects.remove(beanName);
223:                this .registeredSingletons.remove(beanName);
224:            }
225:
226:            public boolean containsSingleton(String beanName) {
227:                return (this .singletonObjects.containsKey(beanName));
228:            }
229:
230:            public String[] getSingletonNames() {
231:                synchronized (this .singletonObjects) {
232:                    return StringUtils.toStringArray(this .registeredSingletons);
233:                }
234:            }
235:
236:            public int getSingletonCount() {
237:                synchronized (this .singletonObjects) {
238:                    return this .registeredSingletons.size();
239:                }
240:            }
241:
242:            /**
243:             * Callback before singleton creation.
244:             * <p>Default implementation register the singleton as currently in creation.
245:             * @param beanName the name of the singleton about to be created
246:             * @see #isSingletonCurrentlyInCreation
247:             */
248:            protected void beforeSingletonCreation(String beanName) {
249:                if (!this .singletonsCurrentlyInCreation.add(beanName)) {
250:                    throw new BeanCurrentlyInCreationException(beanName);
251:                }
252:            }
253:
254:            /**
255:             * Callback after singleton creation.
256:             * <p>Default implementation marks the singleton as not in creation anymore.
257:             * @param beanName the name of the singleton that has been created
258:             * @see #isSingletonCurrentlyInCreation
259:             */
260:            protected void afterSingletonCreation(String beanName) {
261:                if (!this .singletonsCurrentlyInCreation.remove(beanName)) {
262:                    throw new IllegalStateException("Singleton '" + beanName
263:                            + "' isn't currently in creation");
264:                }
265:            }
266:
267:            /**
268:             * Return whether the specified singleton bean is currently in creation
269:             * (within the entire factory).
270:             * @param beanName the name of the bean
271:             */
272:            public final boolean isSingletonCurrentlyInCreation(String beanName) {
273:                return this .singletonsCurrentlyInCreation.contains(beanName);
274:            }
275:
276:            /**
277:             * Add the given bean to the list of disposable beans in this registry.
278:             * Disposable beans usually correspond to registered singletons,
279:             * matching the bean name but potentially being a different instance
280:             * (for example, a DisposableBean adapter for a singleton that does not
281:             * naturally implement Spring's DisposableBean interface).
282:             * @param beanName the name of the bean
283:             * @param bean the bean instance
284:             */
285:            public void registerDisposableBean(String beanName,
286:                    DisposableBean bean) {
287:                synchronized (this .disposableBeans) {
288:                    this .disposableBeans.put(beanName, bean);
289:                }
290:            }
291:
292:            /**
293:             * Register a dependent bean for the given bean,
294:             * to be destroyed before the given bean is destroyed.
295:             * @param beanName the name of the bean
296:             * @param dependentBeanName the name of the dependent bean
297:             */
298:            public void registerDependentBean(String beanName,
299:                    String dependentBeanName) {
300:                synchronized (this .dependentBeanMap) {
301:                    Set dependentBeans = (Set) this .dependentBeanMap
302:                            .get(beanName);
303:                    if (dependentBeans == null) {
304:                        dependentBeans = new LinkedHashSet(8);
305:                        this .dependentBeanMap.put(beanName, dependentBeans);
306:                    }
307:                    dependentBeans.add(dependentBeanName);
308:                }
309:                synchronized (this .dependenciesForBeanMap) {
310:                    Set dependenciesForBean = (Set) this .dependenciesForBeanMap
311:                            .get(dependentBeanName);
312:                    if (dependenciesForBean == null) {
313:                        dependenciesForBean = new LinkedHashSet(8);
314:                        this .dependenciesForBeanMap.put(dependentBeanName,
315:                                dependenciesForBean);
316:                    }
317:                    dependenciesForBean.add(beanName);
318:                }
319:            }
320:
321:            /**
322:             * Determine whether a dependent bean has been registered under the given name.
323:             * @param beanName the name of the bean
324:             */
325:            protected boolean hasDependentBean(String beanName) {
326:                return this .dependentBeanMap.containsKey(beanName);
327:            }
328:
329:            /**
330:             * Return the names of all beans which depend on the specified bean, if any.
331:             * @param beanName the name of the bean
332:             * @return the array of dependent bean names, or an empty array if none
333:             */
334:            public String[] getDependentBeans(String beanName) {
335:                Set dependentBeans = (Set) this .dependentBeanMap.get(beanName);
336:                if (dependentBeans == null) {
337:                    return new String[0];
338:                }
339:                return (String[]) dependentBeans
340:                        .toArray(new String[dependentBeans.size()]);
341:            }
342:
343:            /**
344:             * Return the names of all beans that the specified bean depends on, if any.
345:             * @param beanName the name of the bean
346:             * @return the array of names of beans which the bean depends on,
347:             * or an empty array if none
348:             */
349:            public String[] getDependenciesForBean(String beanName) {
350:                Set dependenciesForBean = (Set) this .dependenciesForBeanMap
351:                        .get(beanName);
352:                if (dependenciesForBean == null) {
353:                    return new String[0];
354:                }
355:                return (String[]) dependenciesForBean
356:                        .toArray(new String[dependenciesForBean.size()]);
357:            }
358:
359:            public void destroySingletons() {
360:                if (logger.isInfoEnabled()) {
361:                    logger.info("Destroying singletons in " + this );
362:                }
363:                synchronized (this .singletonObjects) {
364:                    this .singletonsCurrentlyInDestruction = true;
365:                }
366:                synchronized (this .disposableBeans) {
367:                    String[] disposableBeanNames = StringUtils
368:                            .toStringArray(this .disposableBeans.keySet());
369:                    for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
370:                        destroySingleton(disposableBeanNames[i]);
371:                    }
372:                }
373:                synchronized (this .singletonObjects) {
374:                    this .singletonObjects.clear();
375:                    this .registeredSingletons.clear();
376:                    this .singletonsCurrentlyInDestruction = false;
377:                }
378:            }
379:
380:            /**
381:             * Destroy the given bean. Delegates to <code>destroyBean</code>
382:             * if a corresponding disposable bean instance is found.
383:             * @param beanName the name of the bean
384:             * @see #destroyBean
385:             */
386:            public void destroySingleton(String beanName) {
387:                synchronized (this .singletonObjects) {
388:                    // Remove a registered singleton of the given name, if any.
389:                    removeSingleton(beanName);
390:                }
391:
392:                // Destroy the corresponding DisposableBean instance.
393:                DisposableBean disposableBean = null;
394:                synchronized (this .disposableBeans) {
395:                    disposableBean = (DisposableBean) this .disposableBeans
396:                            .remove(beanName);
397:                }
398:                destroyBean(beanName, disposableBean);
399:            }
400:
401:            /**
402:             * Destroy the given bean. Must destroy beans that depend on the given
403:             * bean before the bean itself. Should not throw any exceptions.
404:             * @param beanName the name of the bean
405:             * @param bean the bean instance to destroy
406:             */
407:            protected void destroyBean(String beanName, DisposableBean bean) {
408:                Set dependencies = (Set) this .dependentBeanMap.remove(beanName);
409:                if (dependencies != null) {
410:                    if (logger.isDebugEnabled()) {
411:                        logger.debug("Retrieved dependent beans for bean '"
412:                                + beanName + "': " + dependencies);
413:                    }
414:                    for (Iterator it = dependencies.iterator(); it.hasNext();) {
415:                        String dependentBeanName = (String) it.next();
416:                        destroySingleton(dependentBeanName);
417:                    }
418:                }
419:                if (bean != null) {
420:                    try {
421:                        bean.destroy();
422:                    } catch (Throwable ex) {
423:                        logger.error("Destroy method on bean with name '"
424:                                + beanName + "' threw an exception", ex);
425:                    }
426:                }
427:            }
428:
429:            /**
430:             * Expose the singleton mutex to subclasses.
431:             * <p>Subclasses should synchronize on the given Object if they perform
432:             * any sort of extended singleton creation phase. In particular, subclasses
433:             * should <i>not</i> have their own mutexes involved in singleton creation,
434:             * to avoid the potential for deadlocks in lazy-init situations.
435:             */
436:            protected final Object getSingletonMutex() {
437:                return this.singletonObjects;
438:            }
439:
440:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.