spring SimpleConstructorNamespaceHandler 源码
spring SimpleConstructorNamespaceHandler 代码
文件路径:/spring-beans/src/main/java/org/springframework/beans/factory/xml/SimpleConstructorNamespaceHandler.java
/*
* Copyright 2002-2021 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.xml;
import java.util.Collection;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
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.ConstructorArgumentValues.ValueHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.core.Conventions;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
/**
* Simple {@code NamespaceHandler} implementation that maps custom
* attributes directly through to bean properties. An important point to note is
* that this {@code NamespaceHandler} does not have a corresponding schema
* since there is no way to know in advance all possible attribute names.
*
* <p>An example of the usage of this {@code NamespaceHandler} is shown below:
*
* <pre class="code">
* <bean id="author" class="..TestBean" c:name="Enescu" c:work-ref="compositions"/>
* </pre>
*
* Here the '{@code c:name}' corresponds directly to the '{@code name}
* ' argument declared on the constructor of class '{@code TestBean}'. The
* '{@code c:work-ref}' attributes corresponds to the '{@code work}'
* argument and, rather than being the concrete value, it contains the name of
* the bean that will be considered as a parameter.
*
* <b>Note</b>: This implementation supports only named parameters - there is no
* support for indexes or types. Furthermore, the names are used as hints by
* the container which, by default, does type introspection.
*
* @author Costin Leau
* @since 3.1
* @see SimplePropertyNamespaceHandler
*/
public class SimpleConstructorNamespaceHandler implements NamespaceHandler {
private static final String REF_SUFFIX = "-ref";
private static final String DELIMITER_PREFIX = "_";
@Override
public void init() {
}
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
parserContext.getReaderContext().error(
"Class [" + getClass().getName() + "] does not support custom elements.", element);
return null;
}
@Override
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
if (node instanceof Attr attr) {
String argName = parserContext.getDelegate().getLocalName(attr).strip();
String argValue = attr.getValue().strip();
ConstructorArgumentValues cvs = definition.getBeanDefinition().getConstructorArgumentValues();
boolean ref = false;
// handle -ref arguments
if (argName.endsWith(REF_SUFFIX)) {
ref = true;
argName = argName.substring(0, argName.length() - REF_SUFFIX.length());
}
ValueHolder valueHolder = new ValueHolder(ref ? new RuntimeBeanReference(argValue) : argValue);
valueHolder.setSource(parserContext.getReaderContext().extractSource(attr));
// handle "escaped"/"_" arguments
if (argName.startsWith(DELIMITER_PREFIX)) {
String arg = argName.substring(1).trim();
// fast default check
if (!StringUtils.hasText(arg)) {
cvs.addGenericArgumentValue(valueHolder);
}
// assume an index otherwise
else {
int index = -1;
try {
index = Integer.parseInt(arg);
}
catch (NumberFormatException ex) {
parserContext.getReaderContext().error(
"Constructor argument '" + argName + "' specifies an invalid integer", attr);
}
if (index < 0) {
parserContext.getReaderContext().error(
"Constructor argument '" + argName + "' specifies a negative index", attr);
}
if (cvs.hasIndexedArgumentValue(index)) {
parserContext.getReaderContext().error(
"Constructor argument '" + argName + "' with index "+ index+" already defined using <constructor-arg>." +
" Only one approach may be used per argument.", attr);
}
cvs.addIndexedArgumentValue(index, valueHolder);
}
}
// no escaping -> ctr name
else {
String name = Conventions.attributeNameToPropertyName(argName);
if (containsArgWithName(name, cvs)) {
parserContext.getReaderContext().error(
"Constructor argument '" + argName + "' already defined using <constructor-arg>." +
" Only one approach may be used per argument.", attr);
}
valueHolder.setName(Conventions.attributeNameToPropertyName(argName));
cvs.addGenericArgumentValue(valueHolder);
}
}
return definition;
}
private boolean containsArgWithName(String name, ConstructorArgumentValues cvs) {
return (checkName(name, cvs.getGenericArgumentValues()) ||
checkName(name, cvs.getIndexedArgumentValues().values()));
}
private boolean checkName(String name, Collection<ValueHolder> values) {
for (ValueHolder holder : values) {
if (name.equals(holder.getName())) {
return true;
}
}
return false;
}
}
相关信息
相关文章
spring AbstractBeanDefinitionParser 源码
spring AbstractSimpleBeanDefinitionParser 源码
spring AbstractSingleBeanDefinitionParser 源码
spring BeanDefinitionDecorator 源码
spring BeanDefinitionDocumentReader 源码
spring BeanDefinitionParser 源码
spring BeanDefinitionParserDelegate 源码
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦