/*
 * Copyright 2002-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory.support;

import java.io.IOException;
import java.util.Collections;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.core.env.Environment;
import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

Abstract base class for bean definition readers which implement the BeanDefinitionReader interface.

Provides common properties like the bean factory to work on and the class loader to use for loading bean classes.

Author:Juergen Hoeller, Chris Beams
See Also:
Since:11.12.2003
/** * Abstract base class for bean definition readers which implement * the {@link BeanDefinitionReader} interface. * * <p>Provides common properties like the bean factory to work on * and the class loader to use for loading bean classes. * * @author Juergen Hoeller * @author Chris Beams * @since 11.12.2003 * @see BeanDefinitionReaderUtils */
public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader, EnvironmentCapable {
Logger available to subclasses.
/** Logger available to subclasses. */
protected final Log logger = LogFactory.getLog(getClass()); private final BeanDefinitionRegistry registry; @Nullable private ResourceLoader resourceLoader; @Nullable private ClassLoader beanClassLoader; private Environment environment; private BeanNameGenerator beanNameGenerator = DefaultBeanNameGenerator.INSTANCE;
Create a new AbstractBeanDefinitionReader for the given bean factory.

If the passed-in bean factory does not only implement the BeanDefinitionRegistry interface but also the ResourceLoader interface, it will be used as default ResourceLoader as well. This will usually be the case for ApplicationContext implementations.

If given a plain BeanDefinitionRegistry, the default ResourceLoader will be a PathMatchingResourcePatternResolver.

If the passed-in bean factory also implements EnvironmentCapable its environment will be used by this reader. Otherwise, the reader will initialize and use a StandardEnvironment. All ApplicationContext implementations are EnvironmentCapable, while normal BeanFactory implementations are not.

Params:
  • registry – the BeanFactory to load bean definitions into, in the form of a BeanDefinitionRegistry
See Also:
/** * Create a new AbstractBeanDefinitionReader for the given bean factory. * <p>If the passed-in bean factory does not only implement the BeanDefinitionRegistry * interface but also the ResourceLoader interface, it will be used as default * ResourceLoader as well. This will usually be the case for * {@link org.springframework.context.ApplicationContext} implementations. * <p>If given a plain BeanDefinitionRegistry, the default ResourceLoader will be a * {@link org.springframework.core.io.support.PathMatchingResourcePatternResolver}. * <p>If the passed-in bean factory also implements {@link EnvironmentCapable} its * environment will be used by this reader. Otherwise, the reader will initialize and * use a {@link StandardEnvironment}. All ApplicationContext implementations are * EnvironmentCapable, while normal BeanFactory implementations are not. * @param registry the BeanFactory to load bean definitions into, * in the form of a BeanDefinitionRegistry * @see #setResourceLoader * @see #setEnvironment */
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); this.registry = registry; // Determine ResourceLoader to use. if (this.registry instanceof ResourceLoader) { this.resourceLoader = (ResourceLoader) this.registry; } else { this.resourceLoader = new PathMatchingResourcePatternResolver(); } // Inherit Environment if possible if (this.registry instanceof EnvironmentCapable) { this.environment = ((EnvironmentCapable) this.registry).getEnvironment(); } else { this.environment = new StandardEnvironment(); } } public final BeanDefinitionRegistry getBeanFactory() { return this.registry; } @Override public final BeanDefinitionRegistry getRegistry() { return this.registry; }
Set the ResourceLoader to use for resource locations. If specifying a ResourcePatternResolver, the bean definition reader will be capable of resolving resource patterns to Resource arrays.

Default is PathMatchingResourcePatternResolver, also capable of resource pattern resolving through the ResourcePatternResolver interface.

Setting this to null suggests that absolute resource loading is not available for this bean definition reader.

See Also:
/** * Set the ResourceLoader to use for resource locations. * If specifying a ResourcePatternResolver, the bean definition reader * will be capable of resolving resource patterns to Resource arrays. * <p>Default is PathMatchingResourcePatternResolver, also capable of * resource pattern resolving through the ResourcePatternResolver interface. * <p>Setting this to {@code null} suggests that absolute resource loading * is not available for this bean definition reader. * @see org.springframework.core.io.support.ResourcePatternResolver * @see org.springframework.core.io.support.PathMatchingResourcePatternResolver */
public void setResourceLoader(@Nullable ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } @Override @Nullable public ResourceLoader getResourceLoader() { return this.resourceLoader; }
Set the ClassLoader to use for bean classes.

Default is null, which suggests to not load bean classes eagerly but rather to just register bean definitions with class names, with the corresponding Classes to be resolved later (or never).

See Also:
/** * Set the ClassLoader to use for bean classes. * <p>Default is {@code null}, which suggests to not load bean classes * eagerly but rather to just register bean definitions with class names, * with the corresponding Classes to be resolved later (or never). * @see Thread#getContextClassLoader() */
public void setBeanClassLoader(@Nullable ClassLoader beanClassLoader) { this.beanClassLoader = beanClassLoader; } @Override @Nullable public ClassLoader getBeanClassLoader() { return this.beanClassLoader; }
Set the Environment to use when reading bean definitions. Most often used for evaluating profile information to determine which bean definitions should be read and which should be omitted.
/** * Set the Environment to use when reading bean definitions. Most often used * for evaluating profile information to determine which bean definitions * should be read and which should be omitted. */
public void setEnvironment(Environment environment) { Assert.notNull(environment, "Environment must not be null"); this.environment = environment; } @Override public Environment getEnvironment() { return this.environment; }
Set the BeanNameGenerator to use for anonymous beans (without explicit bean name specified).

Default is a DefaultBeanNameGenerator.

/** * Set the BeanNameGenerator to use for anonymous beans * (without explicit bean name specified). * <p>Default is a {@link DefaultBeanNameGenerator}. */
public void setBeanNameGenerator(@Nullable BeanNameGenerator beanNameGenerator) { this.beanNameGenerator = (beanNameGenerator != null ? beanNameGenerator : DefaultBeanNameGenerator.INSTANCE); } @Override public BeanNameGenerator getBeanNameGenerator() { return this.beanNameGenerator; } @Override public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException { Assert.notNull(resources, "Resource array must not be null"); int count = 0; for (Resource resource : resources) { count += loadBeanDefinitions(resource); } return count; } @Override public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException { return loadBeanDefinitions(location, null); }
Load bean definitions from the specified resource location.

The location can also be a location pattern, provided that the ResourceLoader of this bean definition reader is a ResourcePatternResolver.

Params:
  • location – the resource location, to be loaded with the ResourceLoader (or ResourcePatternResolver) of this bean definition reader
  • actualResources – a Set to be filled with the actual Resource objects that have been resolved during the loading process. May be null to indicate that the caller is not interested in those Resource objects.
Throws:
See Also:
Returns:the number of bean definitions found
/** * Load bean definitions from the specified resource location. * <p>The location can also be a location pattern, provided that the * ResourceLoader of this bean definition reader is a ResourcePatternResolver. * @param location the resource location, to be loaded with the ResourceLoader * (or ResourcePatternResolver) of this bean definition reader * @param actualResources a Set to be filled with the actual Resource objects * that have been resolved during the loading process. May be {@code null} * to indicate that the caller is not interested in those Resource objects. * @return the number of bean definitions found * @throws BeanDefinitionStoreException in case of loading or parsing errors * @see #getResourceLoader() * @see #loadBeanDefinitions(org.springframework.core.io.Resource) * @see #loadBeanDefinitions(org.springframework.core.io.Resource[]) */
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException { ResourceLoader resourceLoader = getResourceLoader(); if (resourceLoader == null) { throw new BeanDefinitionStoreException( "Cannot load bean definitions from location [" + location + "]: no ResourceLoader available"); } if (resourceLoader instanceof ResourcePatternResolver) { // Resource pattern matching available. try { Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location); int count = loadBeanDefinitions(resources); if (actualResources != null) { Collections.addAll(actualResources, resources); } if (logger.isTraceEnabled()) { logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]"); } return count; } catch (IOException ex) { throw new BeanDefinitionStoreException( "Could not resolve bean definition resource pattern [" + location + "]", ex); } } else { // Can only load single resources by absolute URL. Resource resource = resourceLoader.getResource(location); int count = loadBeanDefinitions(resource); if (actualResources != null) { actualResources.add(resource); } if (logger.isTraceEnabled()) { logger.trace("Loaded " + count + " bean definitions from location [" + location + "]"); } return count; } } @Override public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException { Assert.notNull(locations, "Location array must not be null"); int count = 0; for (String location : locations) { count += loadBeanDefinitions(location); } return count; } }