Source Code Cross Referenced for SingletonBeanFactoryLocator.java in  » J2EE » spring-framework-2.5 » org » springframework » beans » factory » access » 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.access 
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.access;
018:
019:        import java.io.IOException;
020:        import java.util.HashMap;
021:        import java.util.Map;
022:
023:        import org.apache.commons.logging.Log;
024:        import org.apache.commons.logging.LogFactory;
025:
026:        import org.springframework.beans.BeansException;
027:        import org.springframework.beans.FatalBeanException;
028:        import org.springframework.beans.factory.BeanDefinitionStoreException;
029:        import org.springframework.beans.factory.BeanFactory;
030:        import org.springframework.beans.factory.config.ConfigurableBeanFactory;
031:        import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
032:        import org.springframework.beans.factory.support.DefaultListableBeanFactory;
033:        import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
034:        import org.springframework.core.io.Resource;
035:        import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
036:        import org.springframework.core.io.support.ResourcePatternResolver;
037:        import org.springframework.core.io.support.ResourcePatternUtils;
038:
039:        /**
040:         * <p>Keyed-singleton implementation of {@link BeanFactoryLocator},
041:         * which accesses shared Spring {@link BeanFactory} instances.</p>
042:         *
043:         * <p>Please see the warning in BeanFactoryLocator's javadoc about appropriate usage
044:         * of singleton style BeanFactoryLocator implementations. It is the opinion of the 
045:         * Spring team that the use of this class and similar classes is unnecessary except
046:         * (sometimes) for a small amount of glue code. Excessive usage will lead to code
047:         * that is more tightly coupled, and harder to modify or test.</p>
048:         *
049:         * <p>In this implementation, a BeanFactory is built up from one or more XML
050:         * definition file fragments, accessed as resources. The default resource name
051:         * searched for is 'classpath*:beanRefFactory.xml', with the Spring-standard
052:         * 'classpath*:' prefix ensuring that if the classpath contains multiple copies
053:         * of this file (perhaps one in each component jar) they will be combined. To
054:         * override the default resource name, instead of using the no-arg 
055:         * {@link #getInstance()} method, use the {@link #getInstance(String selector)}
056:         * variant, which will treat the 'selector' argument as the resource name to
057:         * search for.</p>
058:         * 
059:         * <p>The purpose of this 'outer' BeanFactory is to create and hold a copy of one
060:         * or more 'inner' BeanFactory or ApplicationContext instances, and allow those
061:         * to be obtained either directly or via an alias. As such, this class provides
062:         * both singleton style access to one or more BeanFactories/ApplicationContexts,
063:         * and also a level of indirection, allowing multiple pieces of code, which are
064:         * not able to work in a Dependency Injection fashion, to refer to and use the
065:         * same target BeanFactory/ApplicationContext instance(s), by different names.<p>
066:         *
067:         * <p>Consider an example application scenario:
068:         *
069:         * <ul>
070:         * <li><code>com.mycompany.myapp.util.applicationContext.xml</code> -
071:         * ApplicationContext definition file which defines beans for 'util' layer.
072:         * <li><code>com.mycompany.myapp.dataaccess-applicationContext.xml</code> -
073:         * ApplicationContext definition file which defines beans for 'data access' layer.
074:         * Depends on the above.
075:         * <li><code>com.mycompany.myapp.services.applicationContext.xml</code> -
076:         * ApplicationContext definition file which defines beans for 'services' layer.
077:         * Depends on the above.
078:         * </ul>
079:         *
080:         * <p>In an ideal scenario, these would be combined to create one ApplicationContext,
081:         * or created as three hierarchical ApplicationContexts, by one piece of code
082:         * somewhere at application startup (perhaps a Servlet filter), from which all other
083:         * code in the application would flow, obtained as beans from the context(s). However
084:         * when third party code enters into the picture, things can get problematic. If the 
085:         * third party code needs to create user classes, which should normally be obtained
086:         * from a Spring BeanFactory/ApplicationContext, but can handle only newInstance()
087:         * style object creation, then some extra work is required to actually access and 
088:         * use object from a BeanFactory/ApplicationContext. One solutions is to make the
089:         * class created by the third party code be just a stub or proxy, which gets the
090:         * real object from a BeanFactory/ApplicationContext, and delegates to it. However,
091:         * it is is not normally workable for the stub to create the BeanFactory on each
092:         * use, as depending on what is inside it, that can be an expensive operation.
093:         * Additionally, there is a fairly tight coupling between the stub and the name of
094:         * the definition resource for the BeanFactory/ApplicationContext. This is where
095:         * SingletonBeanFactoryLocator comes in. The stub can obtain a
096:         * SingletonBeanFactoryLocator instance, which is effectively a singleton, and
097:         * ask it for an appropriate BeanFactory. A subsequent invocation (assuming the
098:         * same class loader is involved) by the stub or another piece of code, will obtain
099:         * the same instance. The simple aliasing mechanism allows the context to be asked
100:         * for by a name which is appropriate for (or describes) the user. The deployer can
101:         * match alias names to actual context names.
102:         *
103:         * <p>Another use of SingletonBeanFactoryLocator, is to demand-load/use one or more
104:         * BeanFactories/ApplicationContexts. Because the definition can contain one of more
105:         * BeanFactories/ApplicationContexts, which can be independent or in a hierarchy, if 
106:         * they are set to lazy-initialize, they will only be created when actually requested
107:         * for use.
108:         *
109:         * <p>Given the above-mentioned three ApplicationContexts, consider the simplest
110:         * SingletonBeanFactoryLocator usage scenario, where there is only one single
111:         * <code>beanRefFactory.xml</code> definition file:
112:         *
113:         * <pre class="code">&lt;?xml version="1.0" encoding="UTF-8"?>
114:         * &lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
115:         * 
116:         * &lt;beans>
117:         * 
118:         *   &lt;bean id="com.mycompany.myapp"
119:         *         class="org.springframework.context.support.ClassPathXmlApplicationContext">
120:         *     &lt;constructor-arg>
121:         *       &lt;list>
122:         *         &lt;value>com/mycompany/myapp/util/applicationContext.xml&lt;/value>
123:         *         &lt;value>com/mycompany/myapp/dataaccess/applicationContext.xml&lt;/value>
124:         *         &lt;value>com/mycompany/myapp/dataaccess/services.xml&lt;/value>
125:         *       &lt;/list>
126:         *     &lt;/constructor-arg>
127:         *   &lt;/bean>
128:         * 
129:         * &lt;/beans>
130:         * </pre>
131:         *
132:         * The client code is as simple as:
133:         *
134:         * <pre class="code">
135:         * BeanFactoryLocator bfl = SingletonBeanFactoryLocator.getInstance();
136:         * BeanFactoryReference bf = bfl.useBeanFactory("com.mycompany.myapp");
137:         * // now use some bean from factory 
138:         * MyClass zed = bf.getFactory().getBean("mybean");
139:         * </pre>
140:         *
141:         * Another relatively simple variation of the <code>beanRefFactory.xml</code> definition file could be:
142:         *
143:         * <pre class="code">&lt;?xml version="1.0" encoding="UTF-8"?>
144:         * &lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
145:         * 
146:         * &lt;beans>
147:         * 
148:         *   &lt;bean id="com.mycompany.myapp.util" lazy-init="true"
149:         *         class="org.springframework.context.support.ClassPathXmlApplicationContext">
150:         *     &lt;constructor-arg>
151:         *       &lt;value>com/mycompany/myapp/util/applicationContext.xml&lt;/value>
152:         *     &lt;/constructor-arg>
153:         *   &lt;/bean>
154:         * 
155:         *   &lt;!-- child of above -->
156:         *   &lt;bean id="com.mycompany.myapp.dataaccess" lazy-init="true"
157:         *         class="org.springframework.context.support.ClassPathXmlApplicationContext">
158:         *     &lt;constructor-arg>
159:         *       &lt;list>&lt;value>com/mycompany/myapp/dataaccess/applicationContext.xml&lt;/value>&lt;/list>
160:         *     &lt;/constructor-arg>
161:         *     &lt;constructor-arg>
162:         *       &lt;ref bean="com.mycompany.myapp.util"/>
163:         *     &lt;/constructor-arg>
164:         *   &lt;/bean>
165:         * 
166:         *   &lt;!-- child of above -->
167:         *   &lt;bean id="com.mycompany.myapp.services" lazy-init="true"
168:         *         class="org.springframework.context.support.ClassPathXmlApplicationContext">
169:         *     &lt;constructor-arg>
170:         *       &lt;list>&lt;value>com/mycompany/myapp/dataaccess.services.xml&lt;/value>&lt;/value>
171:         *     &lt;/constructor-arg>
172:         *     &lt;constructor-arg>
173:         *       &lt;ref bean="com.mycompany.myapp.dataaccess"/>
174:         *     &lt;/constructor-arg>
175:         *   &lt;/bean>
176:         * 
177:         *   &lt;!-- define an alias -->
178:         *   &lt;bean id="com.mycompany.myapp.mypackage"
179:         *         class="java.lang.String">
180:         *     &lt;constructor-arg>
181:         *       &lt;value>com.mycompany.myapp.services&lt;/value>
182:         *     &lt;/constructor-arg>
183:         *   &lt;/bean>
184:         * 
185:         * &lt;/beans>
186:         * </pre>
187:         *
188:         * <p>In this example, there is a hierarchy of three contexts created. The (potential)
189:         * advantage is that if the lazy flag is set to true, a context will only be created
190:         * if it's actually used. If there is some code that is only needed some of the time,
191:         * this mechanism can save some resources. Additionally, an alias to the last context
192:         * has been created. Aliases allow usage of the idiom where client code asks for a
193:         * context with an id which represents the package or module the code is in, and the
194:         * actual definition file(s) for the SingletonBeanFactoryLocator maps that id to
195:         * a real context id.
196:         *
197:         * <p>A final example is more complex, with a <code>beanRefFactory.xml</code> for every module.
198:         * All the files are automatically combined to create the final definition.
199:         *
200:         * <p><code>beanRefFactory.xml</code> file inside jar for util module:
201:         *
202:         * <pre class="code">&lt;?xml version="1.0" encoding="UTF-8"?>
203:         * &lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
204:         * 
205:         * &lt;beans>
206:         *   &lt;bean id="com.mycompany.myapp.util" lazy-init="true"
207:         *        class="org.springframework.context.support.ClassPathXmlApplicationContext">
208:         *     &lt;constructor-arg>
209:         *       &lt;value>com/mycompany/myapp/util/applicationContext.xml&lt;/value>
210:         *     &lt;/constructor-arg>
211:         *   &lt;/bean>
212:         * &lt;/beans>
213:         * </pre>
214:         * 
215:         * <code>beanRefFactory.xml</code> file inside jar for data-access module:<br>
216:         *
217:         * <pre class="code">&lt;?xml version="1.0" encoding="UTF-8"?>
218:         * &lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
219:         * 
220:         * &lt;beans>
221:         *   &lt;!-- child of util -->
222:         *   &lt;bean id="com.mycompany.myapp.dataaccess" lazy-init="true"
223:         *        class="org.springframework.context.support.ClassPathXmlApplicationContext">
224:         *     &lt;constructor-arg>
225:         *       &lt;list>&lt;value>com/mycompany/myapp/dataaccess/applicationContext.xml&lt;/value>&lt;/list>
226:         *     &lt;/constructor-arg>
227:         *     &lt;constructor-arg>
228:         *       &lt;ref bean="com.mycompany.myapp.util"/>
229:         *     &lt;/constructor-arg>
230:         *   &lt;/bean>
231:         * &lt;/beans>
232:         * </pre>
233:         * 
234:         * <code>beanRefFactory.xml</code> file inside jar for services module:
235:         *
236:         * <pre class="code">&lt;?xml version="1.0" encoding="UTF-8"?>
237:         * &lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
238:         * 
239:         * &lt;beans>
240:         *   &lt;!-- child of data-access -->
241:         *   &lt;bean id="com.mycompany.myapp.services" lazy-init="true"
242:         *        class="org.springframework.context.support.ClassPathXmlApplicationContext">
243:         *     &lt;constructor-arg>
244:         *       &lt;list>&lt;value>com/mycompany/myapp/dataaccess/services.xml&lt;/value>&lt;/list>
245:         *     &lt;/constructor-arg>
246:         *     &lt;constructor-arg>
247:         *       &lt;ref bean="com.mycompany.myapp.dataaccess"/>
248:         *     &lt;/constructor-arg>
249:         *   &lt;/bean>
250:         * &lt;/beans>
251:         * </pre>
252:         * 
253:         * <code>beanRefFactory.xml</code> file inside jar for mypackage module. This doesn't
254:         * create any of its own contexts, but allows the other ones to be referred to be
255:         * a name known to this module:
256:         *
257:         * <pre class="code">&lt;?xml version="1.0" encoding="UTF-8"?>
258:         * &lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
259:         * 
260:         * &lt;beans>
261:         *   &lt;!-- define an alias for "com.mycompany.myapp.services" -->
262:         *   &lt;alias name="com.mycompany.myapp.services" alias="com.mycompany.myapp.mypackage"/&gt;
263:         * &lt;/beans>
264:         * </pre>
265:         *   
266:         * @author Colin Sampaleanu
267:         * @author Juergen Hoeller
268:         * @see org.springframework.context.access.ContextSingletonBeanFactoryLocator
269:         * @see org.springframework.context.access.DefaultLocatorFactory
270:         */
271:        public class SingletonBeanFactoryLocator implements  BeanFactoryLocator {
272:
273:            private static final String DEFAULT_RESOURCE_LOCATION = "classpath*:beanRefFactory.xml";
274:
275:            protected static final Log logger = LogFactory
276:                    .getLog(SingletonBeanFactoryLocator.class);
277:
278:            /** The keyed BeanFactory instances */
279:            private static Map instances = new HashMap();
280:
281:            /**
282:             * Returns an instance which uses the default "classpath*:beanRefFactory.xml",
283:             * as the name of the definition file(s). All resources returned by calling the
284:             * current thread context ClassLoader's <code>getResources</code> method with
285:             * this name will be combined to create a BeanFactory definition set.
286:             * @return the corresponding BeanFactoryLocator instance
287:             * @throws BeansException in case of factory loading failure
288:             */
289:            public static BeanFactoryLocator getInstance()
290:                    throws BeansException {
291:                return getInstance(null);
292:            }
293:
294:            /**
295:             * Returns an instance which uses the the specified selector, as the name of the
296:             * definition file(s). In the case of a name with a Spring 'classpath*:' prefix,
297:             * or with no prefix, which is treated the same, the current thread context
298:             * ClassLoader's <code>getResources</code> method will be called with this value
299:             * to get all resources having that name. These resources will then be combined to
300:             * form a definition. In the case where the name uses a Spring 'classpath:' prefix,
301:             * or a standard URL prefix, then only one resource file will be loaded as the
302:             * definition.
303:             * @param selector the name of the resource(s) which will be read and
304:             * combined to form the definition for the BeanFactoryLocator instance.
305:             * Any such files must form a valid BeanFactory definition.
306:             * @return the corresponding BeanFactoryLocator instance
307:             * @throws BeansException in case of factory loading failure
308:             */
309:            public static BeanFactoryLocator getInstance(String selector)
310:                    throws BeansException {
311:                String resourceLocation = selector;
312:                if (resourceLocation == null) {
313:                    resourceLocation = DEFAULT_RESOURCE_LOCATION;
314:                }
315:
316:                // For backwards compatibility, we prepend 'classpath*:' to the selector name if there
317:                // is no other prefix (i.e. classpath*:, classpath:, or some URL prefix.
318:                if (!ResourcePatternUtils.isUrl(resourceLocation)) {
319:                    resourceLocation = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
320:                            + resourceLocation;
321:                }
322:
323:                synchronized (instances) {
324:                    if (logger.isTraceEnabled()) {
325:                        logger
326:                                .trace("SingletonBeanFactoryLocator.getInstance(): instances.hashCode="
327:                                        + instances.hashCode()
328:                                        + ", instances="
329:                                        + instances);
330:                    }
331:                    BeanFactoryLocator bfl = (BeanFactoryLocator) instances
332:                            .get(resourceLocation);
333:                    if (bfl == null) {
334:                        bfl = new SingletonBeanFactoryLocator(resourceLocation);
335:                        instances.put(resourceLocation, bfl);
336:                    }
337:                    return bfl;
338:                }
339:            }
340:
341:            // We map BeanFactoryGroup objects by String keys, and by the definition object.
342:            private final Map bfgInstancesByKey = new HashMap();
343:
344:            private final Map bfgInstancesByObj = new HashMap();
345:
346:            private final String resourceLocation;
347:
348:            /**
349:             * Constructor which uses the the specified name as the resource name
350:             * of the definition file(s).
351:             * @param resourceLocation the Spring resource location to use
352:             * (either a URL or a "classpath:" / "classpath*:" pseudo URL)
353:             */
354:            protected SingletonBeanFactoryLocator(String resourceLocation) {
355:                this .resourceLocation = resourceLocation;
356:            }
357:
358:            public BeanFactoryReference useBeanFactory(String factoryKey)
359:                    throws BeansException {
360:                synchronized (this .bfgInstancesByKey) {
361:                    BeanFactoryGroup bfg = (BeanFactoryGroup) this .bfgInstancesByKey
362:                            .get(this .resourceLocation);
363:
364:                    if (bfg != null) {
365:                        bfg.refCount++;
366:                    } else {
367:                        // This group definition doesn't exist, we need to try to load it.
368:                        if (logger.isTraceEnabled()) {
369:                            logger.trace("Factory group with resource name ["
370:                                    + this .resourceLocation
371:                                    + "] requested. Creating new instance.");
372:                        }
373:
374:                        // Create the BeanFactory but don't initialize it.
375:                        BeanFactory groupContext = createDefinition(
376:                                this .resourceLocation, factoryKey);
377:
378:                        // Record its existence now, before instantiating any singletons.
379:                        bfg = new BeanFactoryGroup();
380:                        bfg.definition = groupContext;
381:                        bfg.refCount = 1;
382:                        this .bfgInstancesByKey.put(this .resourceLocation, bfg);
383:                        this .bfgInstancesByObj.put(groupContext, bfg);
384:
385:                        // Now initialize the BeanFactory. This may cause a re-entrant invocation
386:                        // of this method, but since we've already added the BeanFactory to our
387:                        // mappings, the next time it will be found and simply have its
388:                        // reference count incremented.
389:                        try {
390:                            initializeDefinition(groupContext);
391:                        } catch (BeansException ex) {
392:                            throw new BootstrapException(
393:                                    "Unable to initialize group definition. "
394:                                            + "Group resource name ["
395:                                            + this .resourceLocation
396:                                            + "], factory key [" + factoryKey
397:                                            + "]", ex);
398:                        }
399:                    }
400:
401:                    try {
402:                        BeanFactory beanFactory = (BeanFactory) bfg.definition
403:                                .getBean(factoryKey, BeanFactory.class);
404:                        return new CountingBeanFactoryReference(beanFactory,
405:                                bfg.definition);
406:                    } catch (BeansException ex) {
407:                        throw new BootstrapException(
408:                                "Unable to return specified BeanFactory instance: factory key ["
409:                                        + factoryKey
410:                                        + "], from group with resource name ["
411:                                        + this .resourceLocation + "]", ex);
412:                    }
413:
414:                }
415:            }
416:
417:            /**
418:             * Actually creates definition in the form of a BeanFactory, given a resource name
419:             * which supports standard Spring resource prefixes ('classpath:', 'classpath*:', etc.)
420:             * This is split out as a separate method so that subclasses can override the actual
421:             * type used (to be an ApplicationContext, for example).
422:             * <p>The default implementation simply builds a
423:             * {@link org.springframework.beans.factory.support.DefaultListableBeanFactory}
424:             * and populates it using an
425:             * {@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader}.
426:             * <p>This method should not instantiate any singletons. That function is performed
427:             * by {@link #initializeDefinition initializeDefinition()}, which should also be
428:             * overridden if this method is.
429:             * @param resourceLocation the resource location for this factory group
430:             * @param factoryKey the bean name of the factory to obtain
431:             * @return the corresponding BeanFactory reference
432:             */
433:            protected BeanFactory createDefinition(String resourceLocation,
434:                    String factoryKey) {
435:                DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
436:                XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(
437:                        factory);
438:                ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
439:
440:                try {
441:                    Resource[] configResources = resourcePatternResolver
442:                            .getResources(resourceLocation);
443:                    if (configResources.length == 0) {
444:                        throw new FatalBeanException(
445:                                "Unable to find resource for specified definition. "
446:                                        + "Group resource name ["
447:                                        + this .resourceLocation
448:                                        + "], factory key [" + factoryKey + "]");
449:                    }
450:                    reader.loadBeanDefinitions(configResources);
451:                } catch (IOException ex) {
452:                    throw new BeanDefinitionStoreException(
453:                            "Error accessing bean definition resource ["
454:                                    + this .resourceLocation + "]", ex);
455:                } catch (BeanDefinitionStoreException ex) {
456:                    throw new FatalBeanException(
457:                            "Unable to load group definition: "
458:                                    + "group resource name ["
459:                                    + this .resourceLocation
460:                                    + "], factory key [" + factoryKey + "]", ex);
461:                }
462:
463:                return factory;
464:            }
465:
466:            /**
467:             * Instantiate singletons and do any other normal initialization of the factory.
468:             * Subclasses that override {@link #createDefinition createDefinition()} should
469:             * also override this method.
470:             * @param groupDef the factory returned by {@link #createDefinition createDefinition()}
471:             */
472:            protected void initializeDefinition(BeanFactory groupDef) {
473:                if (groupDef instanceof  ConfigurableListableBeanFactory) {
474:                    ((ConfigurableListableBeanFactory) groupDef)
475:                            .preInstantiateSingletons();
476:                }
477:            }
478:
479:            /**
480:             * Destroy definition in separate method so subclass may work with other definition types.
481:             * @param groupDef the factory returned by {@link #createDefinition createDefinition()}
482:             * @param selector the resource location for this factory group
483:             */
484:            protected void destroyDefinition(BeanFactory groupDef,
485:                    String selector) {
486:                if (groupDef instanceof  ConfigurableBeanFactory) {
487:                    if (logger.isTraceEnabled()) {
488:                        logger
489:                                .trace("Factory group with selector '"
490:                                        + selector
491:                                        + "' being released, as there are no more references to it");
492:                    }
493:                    ((ConfigurableBeanFactory) groupDef).destroySingletons();
494:                }
495:            }
496:
497:            /**
498:             * We track BeanFactory instances with this class.
499:             */
500:            private static class BeanFactoryGroup {
501:
502:                private BeanFactory definition;
503:
504:                private int refCount = 0;
505:            }
506:
507:            /**
508:             * BeanFactoryReference implementation for this locator.
509:             */
510:            private class CountingBeanFactoryReference implements 
511:                    BeanFactoryReference {
512:
513:                private BeanFactory beanFactory;
514:
515:                private BeanFactory groupContextRef;
516:
517:                public CountingBeanFactoryReference(BeanFactory beanFactory,
518:                        BeanFactory groupContext) {
519:                    this .beanFactory = beanFactory;
520:                    this .groupContextRef = groupContext;
521:                }
522:
523:                public BeanFactory getFactory() {
524:                    return this .beanFactory;
525:                }
526:
527:                // Note that it's legal to call release more than once!
528:                public void release() throws FatalBeanException {
529:                    synchronized (bfgInstancesByKey) {
530:                        BeanFactory savedRef = this .groupContextRef;
531:                        if (savedRef != null) {
532:                            this .groupContextRef = null;
533:                            BeanFactoryGroup bfg = (BeanFactoryGroup) bfgInstancesByObj
534:                                    .get(savedRef);
535:                            if (bfg != null) {
536:                                bfg.refCount--;
537:                                if (bfg.refCount == 0) {
538:                                    destroyDefinition(savedRef,
539:                                            resourceLocation);
540:                                    bfgInstancesByKey.remove(resourceLocation);
541:                                    bfgInstancesByObj.remove(savedRef);
542:                                }
543:                            } else {
544:                                // This should be impossible.
545:                                logger
546:                                        .warn("Tried to release a SingletonBeanFactoryLocator group definition "
547:                                                + "more times than it has actually been used. Resource name ["
548:                                                + resourceLocation + "]");
549:                            }
550:                        }
551:                    }
552:                }
553:            }
554:
555:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.