📄 defaultxmlbeandefinitionparser.java
字号:
/*
* Copyright 2002-2004 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
*
* http://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.xml;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Comment;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionReader;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.LookupOverride;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.support.ManagedSet;
import org.springframework.beans.factory.support.MethodOverrides;
import org.springframework.beans.factory.support.ReplaceOverride;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;
/**
* Default implementation of the XmlBeanDefinitionParser interface.
* Parses bean definitions according to the "spring-beans" DTD,
* i.e. Spring's default XML bean definition format.
*
* <p>The structure, elements and attribute names of the required XML document
* are hard-coded in this class. (Of course a transform could be run if necessary
* to produce this format). "beans" doesn't need to be the root element of the XML
* document: This class will parse all bean definition elements in the XML file.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @since 18.12.2003
*/
public class DefaultXmlBeanDefinitionParser implements XmlBeanDefinitionParser {
public static final String BEAN_NAME_DELIMITERS = ",; ";
/**
* Value of a T/F attribute that represents true.
* Anything else represents false. Case seNsItive.
*/
public static final String TRUE_VALUE = "true";
public static final String DEFAULT_VALUE = "default";
public static final String DESCRIPTION_ELEMENT = "description";
public static final String AUTOWIRE_BY_NAME_VALUE = "byName";
public static final String AUTOWIRE_BY_TYPE_VALUE = "byType";
public static final String AUTOWIRE_CONSTRUCTOR_VALUE = "constructor";
public static final String AUTOWIRE_AUTODETECT_VALUE = "autodetect";
public static final String DEPENDENCY_CHECK_ALL_ATTRIBUTE_VALUE = "all";
public static final String DEPENDENCY_CHECK_SIMPLE_ATTRIBUTE_VALUE = "simple";
public static final String DEPENDENCY_CHECK_OBJECTS_ATTRIBUTE_VALUE = "objects";
public static final String DEFAULT_LAZY_INIT_ATTRIBUTE = "default-lazy-init";
public static final String DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE = "default-dependency-check";
public static final String DEFAULT_AUTOWIRE_ATTRIBUTE = "default-autowire";
public static final String IMPORT_ELEMENT = "import";
public static final String RESOURCE_ATTRIBUTE = "resource";
public static final String BEAN_ELEMENT = "bean";
public static final String ID_ATTRIBUTE = "id";
public static final String NAME_ATTRIBUTE = "name";
public static final String PARENT_ATTRIBUTE = "parent";
public static final String CLASS_ATTRIBUTE = "class";
public static final String ABSTRACT_ATTRIBUTE = "abstract";
public static final String SINGLETON_ATTRIBUTE = "singleton";
public static final String LAZY_INIT_ATTRIBUTE = "lazy-init";
public static final String AUTOWIRE_ATTRIBUTE = "autowire";
public static final String DEPENDENCY_CHECK_ATTRIBUTE = "dependency-check";
public static final String DEPENDS_ON_ATTRIBUTE = "depends-on";
public static final String INIT_METHOD_ATTRIBUTE = "init-method";
public static final String DESTROY_METHOD_ATTRIBUTE = "destroy-method";
public static final String FACTORY_METHOD_ATTRIBUTE = "factory-method";
public static final String FACTORY_BEAN_ATTRIBUTE = "factory-bean";
public static final String CONSTRUCTOR_ARG_ELEMENT = "constructor-arg";
public static final String INDEX_ATTRIBUTE = "index";
public static final String TYPE_ATTRIBUTE = "type";
public static final String PROPERTY_ELEMENT = "property";
public static final String LOOKUP_METHOD_ELEMENT = "lookup-method";
public static final String REPLACED_METHOD_ELEMENT = "replaced-method";
public static final String REPLACER_ATTRIBUTE = "replacer";
public static final String ARG_TYPE_ELEMENT = "arg-type";
public static final String ARG_TYPE_MATCH_ATTRIBUTE = "match";
public static final String REF_ELEMENT = "ref";
public static final String IDREF_ELEMENT = "idref";
public static final String BEAN_REF_ATTRIBUTE = "bean";
public static final String LOCAL_REF_ATTRIBUTE = "local";
public static final String PARENT_REF_ATTRIBUTE = "parent";
public static final String LIST_ELEMENT = "list";
public static final String SET_ELEMENT = "set";
public static final String MAP_ELEMENT = "map";
public static final String ENTRY_ELEMENT = "entry";
public static final String KEY_ATTRIBUTE = "key";
public static final String PROPS_ELEMENT = "props";
public static final String PROP_ELEMENT = "prop";
public static final String VALUE_ELEMENT = "value";
public static final String NULL_ELEMENT = "null";
protected final Log logger = LogFactory.getLog(getClass());
private BeanDefinitionReader beanDefinitionReader;
private Resource resource;
private String defaultLazyInit;
private String defaultDependencyCheck;
private String defaultAutowire;
public int registerBeanDefinitions(BeanDefinitionReader reader, Document doc, Resource resource)
throws BeansException {
this.beanDefinitionReader = reader;
this.resource = resource;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
this.defaultLazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE);
this.defaultDependencyCheck = root.getAttribute(DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE);
this.defaultAutowire = root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE);
if (logger.isDebugEnabled()) {
logger.debug("Default lazy init '" + this.defaultLazyInit + "'");
logger.debug("Default dependency check '" + this.defaultDependencyCheck + "'");
logger.debug("Default autowire '" + this.defaultAutowire + "'");
}
NodeList nl = root.getChildNodes();
int beanDefinitionCounter = 0;
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (IMPORT_ELEMENT.equals(node.getNodeName())) {
importBeanDefinitionResource(ele);
}
else if (BEAN_ELEMENT.equals(node.getNodeName())) {
beanDefinitionCounter++;
BeanDefinitionHolder bdHolder = parseBeanDefinition(ele);
BeanDefinitionReaderUtils.registerBeanDefinition(
bdHolder, this.beanDefinitionReader.getBeanFactory());
}
}
}
if (logger.isDebugEnabled()) {
logger.debug("Found " + beanDefinitionCounter + " <" + BEAN_ELEMENT + "> elements defining beans");
}
return beanDefinitionCounter;
}
protected BeanDefinitionReader getBeanDefinitionReader() {
return beanDefinitionReader;
}
protected String getDefaultLazyInit() {
return defaultLazyInit;
}
protected String getDefaultDependencyCheck() {
return defaultDependencyCheck;
}
protected String getDefaultAutowire() {
return defaultAutowire;
}
protected Resource getResource() {
return resource;
}
/**
* Parse an "import" element and load the bean definitions
* from the given resource into the bean factory.
*/
protected void importBeanDefinitionResource(Element ele) {
String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
Resource relativeResource = null;
if (ResourceUtils.isUrl(location)) {
ResourceLoader resourceLoader = this.beanDefinitionReader.getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot import bean definitions from location [" + location + "]: no resource loader available");
}
relativeResource = resourceLoader.getResource(location);
}
else {
try {
relativeResource = this.resource.createRelative(location);
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Invalid relative resource location [" + location + "] to import bean definitions from", ex);
}
}
this.beanDefinitionReader.loadBeanDefinitions(relativeResource);
}
/**
* Parse a standard bean definition into a BeanDefinitionHolder,
* including bean name and aliases.
* <p>Bean elements specify their canonical name as "id" attribute
* and their aliases as a delimited "name" attribute.
* <p>If no "id" specified, uses the first name in the "name" attribute
* as canonical name, registering all others as aliases.
*/
protected BeanDefinitionHolder parseBeanDefinition(Element ele) {
String id = ele.getAttribute(ID_ATTRIBUTE);
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List aliases = new ArrayList();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, BEAN_NAME_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = (String) aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
BeanDefinition beanDefinition = parseBeanDefinition(ele, beanName);
if (!StringUtils.hasText(beanName) && beanDefinition instanceof AbstractBeanDefinition) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
(AbstractBeanDefinition) beanDefinition, this.beanDefinitionReader.getBeanFactory());
if (logger.isDebugEnabled()) {
logger.debug("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
String[] aliasesArray = (String[]) aliases.toArray(new String[aliases.size()]);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
/**
* Parse the BeanDefinition itself, without regard to name or aliases.
*/
protected BeanDefinition parseBeanDefinition(Element ele, String beanName) {
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE);
}
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
try {
ConstructorArgumentValues cargs = getConstructorArgSubElements(ele, beanName);
MutablePropertyValues pvs = getPropertyValueSubElements(ele, beanName);
AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition(
className, parent, cargs, pvs, this.beanDefinitionReader.getBeanClassLoader());
if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, BEAN_NAME_DELIMITERS));
}
if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
}
if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
}
String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
if (DEFAULT_VALUE.equals(dependencyCheck)) {
dependencyCheck = this.defaultDependencyCheck;
}
bd.setDependencyCheck(getDependencyCheck(dependencyCheck));
String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
if (DEFAULT_VALUE.equals(autowire)) {
autowire = this.defaultAutowire;
}
bd.setAutowireMode(getAutowireMode(autowire));
String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
if (!initMethodName.equals("")) {
bd.setInitMethodName(initMethodName);
}
String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
if (!destroyMethodName.equals("")) {
bd.setDestroyMethodName(destroyMethodName);
}
getLookupOverrideSubElements(ele, beanName, bd.getMethodOverrides());
getReplacedMethodSubElements(ele, beanName, bd.getMethodOverrides());
bd.setResourceDescription(this.resource.getDescription());
if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
}
if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
bd.setSingleton(TRUE_VALUE.equals(ele.getAttribute(SINGLETON_ATTRIBUTE)));
}
String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
if (DEFAULT_VALUE.equals(lazyInit) && bd.isSingleton()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -