public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext, DisposableBean
1 @Override 2 public void refresh() throws BeansException, IllegalStateException { 3 synchronized (this.startupShutdownMonitor) { 4 // Prepare this context for refreshing. 5 prepareRefresh(); 6 7 // Tell the subclass to refresh the internal bean factory. 8 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 9 10 // Prepare the bean factory for use in this context. 11 prepareBeanFactory(beanFactory); 12 13 try { 14 // Allows post-processing of the bean factory in context subclasses. 15 postProcessBeanFactory(beanFactory); 16 17 // Invoke factory processors registered as beans in the context. 18 invokeBeanFactoryPostProcessors(beanFactory); 19 20 // Register bean processors that intercept bean creation. 21 registerBeanPostProcessors(beanFactory); 22 23 // Initialize message source for this context. 24 initMessageSource(); 25 26 // Initialize event multicaster for this context. 27 initApplicationEventMulticaster(); 28 29 // Initialize other special beans in specific context subclasses. 30 onRefresh(); 31 32 // Check for listener beans and register them. 33 registerListeners(); 34 35 // Instantiate all remaining (non-lazy-init) singletons. 36 finishBeanFactoryInitialization(beanFactory); 37 38 // Last step: publish corresponding event. 39 finishRefresh(); 40 } 41 42 catch (BeansException ex) { 43 // Destroy already created singletons to avoid dangling resources. 44 destroyBeans(); 45 46 // Reset 'active' flag. 47 cancelRefresh(ex); 48 49 // Propagate exception to caller. 50 throw ex; 51 } 52 } 53 }
1 /** 2 * Tell the subclass to refresh the internal bean factory. 3 * @return the fresh BeanFactory instance 4 * @see #refreshBeanFactory() 5 * @see #getBeanFactory() 6 */ 7 protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { 8 refreshBeanFactory(); 9 ConfigurableListableBeanFactory beanFactory = getBeanFactory(); 10 if (logger.isDebugEnabled()) { 11 logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); 12 } 13 return beanFactory; 14 }
1 public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext { 2 3 4 /** 5 * This implementation performs an actual refresh of this context's underlying 6 * bean factory, shutting down the previous bean factory (if any) and 7 * initializing a fresh bean factory for the next phase of the context's lifecycle. 8 */ 9 @Override 10 protected final void refreshBeanFactory() throws BeansException { 11 if (hasBeanFactory()) { 12 destroyBeans(); 13 closeBeanFactory(); 14 } 15 try { 16 DefaultListableBeanFactory beanFactory = createBeanFactory(); 17 beanFactory.setSerializationId(getId()); 18 customizeBeanFactory(beanFactory); 19 loadBeanDefinitions(beanFactory); 20 synchronized (this.beanFactoryMonitor) { 21 this.beanFactory = beanFactory; 22 } 23 } 24 catch (IOException ex) { 25 throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); 26 } 27 } 28 }
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext { /** * Loads the bean definitions via an XmlBeanDefinitionReader. * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader * @see #initBeanDefinitionReader * @see #loadBeanDefinitions */ @Override protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // Create a new XmlBeanDefinitionReader for the given BeanFactory. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // Configure the bean definition reader with this context's // resource loading environment. beanDefinitionReader.setEnvironment(this.getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // Allow a subclass to provide custom initialization of the reader, // then proceed with actually loading the bean definitions. initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); } /** * Load the bean definitions with the given XmlBeanDefinitionReader. * <p>The lifecycle of the bean factory is handled by the {@link #refreshBeanFactory} * method; hence this method is just supposed to load and/or register bean definitions. * @param reader the XmlBeanDefinitionReader to use * @throws BeansException in case of bean registration errors * @throws IOException if the required XML document isn't found * @see #refreshBeanFactory * @see #getConfigLocations * @see #getResources * @see #getResourcePatternResolver */ protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { Resource[] configResources = getConfigResources(); if (configResources != null) { reader.loadBeanDefinitions(configResources); } String[] configLocations = getConfigLocations(); if (configLocations != null) { reader.loadBeanDefinitions(configLocations); } } }
1 public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable, BeanDefinitionReader { 2 @Override 3 public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException { 4 Assert.notNull(locations, "Location array must not be null"); 5 int counter = 0; 6 for (String location : locations) { 7 counter += loadBeanDefinitions(location); 8 } 9 return counter; 10 } 11 12 @Override 13 public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException { 14 return loadBeanDefinitions(location, null); 15 } 16 17 /** 18 * Load bean definitions from the specified resource location. 19 * <p>The location can also be a location pattern, provided that the 20 * ResourceLoader of this bean definition reader is a ResourcePatternResolver. 21 * @param location the resource location, to be loaded with the ResourceLoader 22 * (or ResourcePatternResolver) of this bean definition reader 23 * @param actualResources a Set to be filled with the actual Resource objects 24 * that have been resolved during the loading process. May be {@code null} 25 * to indicate that the caller is not interested in those Resource objects. 26 * @return the number of bean definitions found 27 * @throws BeanDefinitionStoreException in case of loading or parsing errors 28 * @see #getResourceLoader() 29 * @see #loadBeanDefinitions(org.springframework.core.io.Resource) 30 * @see #loadBeanDefinitions(org.springframework.core.io.Resource[]) 31 */ 32 public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException { 33 ResourceLoader resourceLoader = getResourceLoader(); 34 if (resourceLoader == null) { 35 throw new BeanDefinitionStoreException( 36 "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available"); 37 } 38 39 if (resourceLoader instanceof ResourcePatternResolver) { 40 // Resource pattern matching available. 41 try { 42 Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location); 43 int loadCount = loadBeanDefinitions(resources); 44 if (actualResources != null) { 45 for (Resource resource : resources) { 46 actualResources.add(resource); 47 } 48 } 49 if (logger.isDebugEnabled()) { 50 logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]"); 51 } 52 return loadCount; 53 } 54 catch (IOException ex) { 55 throw new BeanDefinitionStoreException( 56 "Could not resolve bean definition resource pattern [" + location + "]", ex); 57 } 58 } 59 else { 60 // Can only load single resources by absolute URL. 61 Resource resource = resourceLoader.getResource(location); 62 int loadCount = loadBeanDefinitions(resource); 63 if (actualResources != null) { 64 actualResources.add(resource); 65 } 66 if (logger.isDebugEnabled()) { 67 logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]"); 68 } 69 return loadCount; 70 } 71 } 72 @Override 73 public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException { 74 Assert.notNull(resources, "Resource array must not be null"); 75 int counter = 0; 76 for (Resource resource : resources) { 77 counter += loadBeanDefinitions(resource); 78 } 79 return counter; 80 } 81 }
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader { /** * Load bean definitions from the specified XML file. * @param resource the resource descriptor for the XML file * @return the number of bean definitions found * @throws BeanDefinitionStoreException in case of loading or parsing errors */ @Override public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException { return loadBeanDefinitions(new EncodedResource(resource)); } /** * Load bean definitions from the specified XML file. * @param encodedResource the resource descriptor for the XML file, * allowing to specify an encoding to use for parsing the file * @return the number of bean definitions found * @throws BeanDefinitionStoreException in case of loading or parsing errors */ public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { Assert.notNull(encodedResource, "EncodedResource must not be null"); if (logger.isInfoEnabled()) { logger.info("Loading XML bean definitions from " + encodedResource.getResource()); } Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get(); if (currentResources == null) { currentResources = new HashSet<EncodedResource>(4); this.resourcesCurrentlyBeingLoaded.set(currentResources); } if (!currentResources.add(encodedResource)) { throw new BeanDefinitionStoreException( "Detected cyclic loading of " + encodedResource + " - check your import definitions!"); } try { InputStream inputStream = encodedResource.getResource().getInputStream(); try { InputSource inputSource = new InputSource(inputStream); if (encodedResource.getEncoding() != null) { inputSource.setEncoding(encodedResource.getEncoding()); } return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); } finally { inputStream.close(); } } catch (IOException ex) { throw new BeanDefinitionStoreException( "IOException parsing XML document from " + encodedResource.getResource(), ex); } finally { currentResources.remove(encodedResource); if (currentResources.isEmpty()) { this.resourcesCurrentlyBeingLoaded.remove(); } } } /** * Actually load bean definitions from the specified XML file. * @param inputSource the SAX InputSource to read from * @param resource the resource descriptor for the XML file * @return the number of bean definitions found * @throws BeanDefinitionStoreException in case of loading or parsing errors * @see #doLoadDocument * @see #registerBeanDefinitions */ protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try { Document doc = doLoadDocument(inputSource, resource); return registerBeanDefinitions(doc, resource); } catch (BeanDefinitionStoreException ex) { throw ex; } catch (SAXParseException ex) { throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex); } catch (SAXException ex) { throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", ex); } catch (ParserConfigurationException ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, ex); } catch (IOException ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, ex); } catch (Throwable ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, ex); } } /** * Register the bean definitions contained in the given DOM document. * Called by {@code loadBeanDefinitions}. * <p>Creates a new instance of the parser class and invokes * {@code registerBeanDefinitions} on it. * @param doc the DOM document * @param resource the resource descriptor (for context information) * @return the number of bean definitions found * @throws BeanDefinitionStoreException in case of parsing errors * @see #loadBeanDefinitions * @see #setDocumentReaderClass * @see BeanDefinitionDocumentReader#registerBeanDefinitions */ public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); documentReader.setEnvironment(this.getEnvironment()); int countBefore = getRegistry().getBeanDefinitionCount(); documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; } }
public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader { /** * {@inheritDoc} * <p>This implementation parses bean definitions according to the "spring-beans" XSD * (or DTD, historically). * <p>Opens a DOM Document; then initializes the default settings * specified at the {@code <beans/>} level; then parses the contained bean definitions. */ @Override public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; logger.debug("Loading bean definitions"); Element root = doc.getDocumentElement(); doRegisterBeanDefinitions(root); } /** * Register each bean definition within the given root {@code <beans/>} element. * @throws IllegalStateException if {@code <beans profile="..."} attribute is present * and Environment property has not been set * @see #setEnvironment */ protected void doRegisterBeanDefinitions(Element root) { String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); if (StringUtils.hasText(profileSpec)) { Assert.state(this.environment != null, "Environment must be set for evaluating profiles"); String[] specifiedProfiles = StringUtils.tokenizeToStringArray( profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); if (!this.environment.acceptsProfiles(specifiedProfiles)) { return; } } // Any nested <beans> elements will cause recursion in this method. In // order to propagate and preserve <beans> default-* attributes correctly, // keep track of the current (parent) delegate, which may be null. Create // the new (child) delegate with a reference to the parent for fallback purposes, // then ultimately reset this.delegate back to its original (parent) reference. // this behavior emulates a stack of delegates without actually necessitating one. BeanDefinitionParserDelegate parent = this.delegate; this.delegate = createDelegate(this.readerContext, root, parent); preProcessXml(root); parseBeanDefinitions(root, this.delegate); postProcessXml(root); this.delegate = parent; } /** * Parse the elements at the root level in the document: * "import", "alias", "bean". * @param root the DOM root element of the document */ protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { if (delegate.isDefaultNamespace(root)) { NodeList nl = root.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); if (node instanceof Element) { Element ele = (Element) node; if (delegate.isDefaultNamespace(ele)) { parseDefaultElement(ele, delegate); } else { delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } } private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { importBeanDefinitionResource(ele); } else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { processAliasRegistration(ele); } else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { processBeanDefinition(ele, delegate); } else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // recurse doRegisterBeanDefinitions(ele); } } }
public class BeanDefinitionParserDelegate { public BeanDefinition parseCustomElement(Element ele) { return parseCustomElement(ele, null); } public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) { String namespaceUri = getNamespaceURI(ele); NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); return null; } return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); } }