001/*
002 * Copyright 2002-2017 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 *      https://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
017package org.springframework.context.support;
018
019import java.io.IOException;
020
021import org.springframework.beans.BeansException;
022import org.springframework.beans.factory.support.DefaultListableBeanFactory;
023import org.springframework.beans.factory.xml.ResourceEntityResolver;
024import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
025import org.springframework.context.ApplicationContext;
026import org.springframework.core.io.Resource;
027import org.springframework.lang.Nullable;
028
029/**
030 * Convenient base class for {@link org.springframework.context.ApplicationContext}
031 * implementations, drawing configuration from XML documents containing bean definitions
032 * understood by an {@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader}.
033 *
034 * <p>Subclasses just have to implement the {@link #getConfigResources} and/or
035 * the {@link #getConfigLocations} method. Furthermore, they might override
036 * the {@link #getResourceByPath} hook to interpret relative paths in an
037 * environment-specific fashion, and/or {@link #getResourcePatternResolver}
038 * for extended pattern resolution.
039 *
040 * @author Rod Johnson
041 * @author Juergen Hoeller
042 * @see #getConfigResources
043 * @see #getConfigLocations
044 * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
045 */
046public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {
047
048        private boolean validating = true;
049
050
051        /**
052         * Create a new AbstractXmlApplicationContext with no parent.
053         */
054        public AbstractXmlApplicationContext() {
055        }
056
057        /**
058         * Create a new AbstractXmlApplicationContext with the given parent context.
059         * @param parent the parent context
060         */
061        public AbstractXmlApplicationContext(@Nullable ApplicationContext parent) {
062                super(parent);
063        }
064
065
066        /**
067         * Set whether to use XML validation. Default is {@code true}.
068         */
069        public void setValidating(boolean validating) {
070                this.validating = validating;
071        }
072
073
074        /**
075         * Loads the bean definitions via an XmlBeanDefinitionReader.
076         * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
077         * @see #initBeanDefinitionReader
078         * @see #loadBeanDefinitions
079         */
080        @Override
081        protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
082                // Create a new XmlBeanDefinitionReader for the given BeanFactory.
083                XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
084
085                // Configure the bean definition reader with this context's
086                // resource loading environment.
087                beanDefinitionReader.setEnvironment(this.getEnvironment());
088                beanDefinitionReader.setResourceLoader(this);
089                beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
090
091                // Allow a subclass to provide custom initialization of the reader,
092                // then proceed with actually loading the bean definitions.
093                initBeanDefinitionReader(beanDefinitionReader);
094                loadBeanDefinitions(beanDefinitionReader);
095        }
096
097        /**
098         * Initialize the bean definition reader used for loading the bean
099         * definitions of this context. Default implementation is empty.
100         * <p>Can be overridden in subclasses, e.g. for turning off XML validation
101         * or using a different XmlBeanDefinitionParser implementation.
102         * @param reader the bean definition reader used by this context
103         * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader#setDocumentReaderClass
104         */
105        protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
106                reader.setValidating(this.validating);
107        }
108
109        /**
110         * Load the bean definitions with the given XmlBeanDefinitionReader.
111         * <p>The lifecycle of the bean factory is handled by the {@link #refreshBeanFactory}
112         * method; hence this method is just supposed to load and/or register bean definitions.
113         * @param reader the XmlBeanDefinitionReader to use
114         * @throws BeansException in case of bean registration errors
115         * @throws IOException if the required XML document isn't found
116         * @see #refreshBeanFactory
117         * @see #getConfigLocations
118         * @see #getResources
119         * @see #getResourcePatternResolver
120         */
121        protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
122                Resource[] configResources = getConfigResources();
123                if (configResources != null) {
124                        reader.loadBeanDefinitions(configResources);
125                }
126                String[] configLocations = getConfigLocations();
127                if (configLocations != null) {
128                        reader.loadBeanDefinitions(configLocations);
129                }
130        }
131
132        /**
133         * Return an array of Resource objects, referring to the XML bean definition
134         * files that this context should be built with.
135         * <p>The default implementation returns {@code null}. Subclasses can override
136         * this to provide pre-built Resource objects rather than location Strings.
137         * @return an array of Resource objects, or {@code null} if none
138         * @see #getConfigLocations()
139         */
140        @Nullable
141        protected Resource[] getConfigResources() {
142                return null;
143        }
144
145}