spring-batch AbstractStepParser 源码
spring-batch AbstractStepParser 代码
文件路径:/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractStepParser.java
/*
* Copyright 2006-2022 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.batch.core.configuration.xml;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.springframework.batch.core.listener.StepListenerMetaData;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
/**
* Internal parser for the <step/> elements inside a job. A step element references
* a bean definition for a {@link org.springframework.batch.core.Step} and goes on to
* (optionally) list a set of transitions from that step to others with <next
* on="pattern" to="stepName"/>. Used by the {@link JobParser}.
*
* @author Dave Syer
* @author Thomas Risberg
* @author Josh Long
* @see JobParser
* @since 2.0
*/
public abstract class AbstractStepParser {
/**
* The ID attribute for the step parser.
*/
protected static final String ID_ATTR = "id";
private static final String PARENT_ATTR = "parent";
private static final String REF_ATTR = "ref";
private static final String ALLOW_START_ATTR = "allow-start-if-complete";
private static final String TASKLET_ELE = "tasklet";
private static final String PARTITION_ELE = "partition";
private static final String JOB_ELE = "job";
private static final String JOB_PARAMS_EXTRACTOR_ATTR = "job-parameters-extractor";
private static final String JOB_LAUNCHER_ATTR = "job-launcher";
private static final String STEP_ATTR = "step";
private static final String STEP_ELE = STEP_ATTR;
private static final String PARTITIONER_ATTR = "partitioner";
private static final String AGGREGATOR_ATTR = "aggregator";
private static final String HANDLER_ATTR = "handler";
private static final String HANDLER_ELE = "handler";
private static final String TASK_EXECUTOR_ATTR = "task-executor";
private static final String GRID_SIZE_ATTR = "grid-size";
private static final String FLOW_ELE = "flow";
private static final String JOB_REPO_ATTR = "job-repository";
private static final StepListenerParser stepListenerParser = new StepListenerParser(
StepListenerMetaData.stepExecutionListenerMetaData());
/**
* @param stepElement The <step/> element
* @param parserContext instance of {@link ParserContext}.
* @param jobFactoryRef the reference to the {@link JobParserJobFactoryBean} from the
* enclosing tag. Use 'null' if unknown.
* @return {@link AbstractBeanDefinition} for the stepElement.
*/
protected AbstractBeanDefinition parseStep(Element stepElement, ParserContext parserContext, String jobFactoryRef) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
AbstractBeanDefinition bd = builder.getRawBeanDefinition();
// look at all nested elements
NodeList children = stepElement.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node nd = children.item(i);
if (nd instanceof Element) {
Element nestedElement = (Element) nd;
String name = nestedElement.getLocalName();
if (TASKLET_ELE.equals(name)) {
boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement);
new TaskletParser().parseTasklet(stepElement, nestedElement, bd, parserContext, stepUnderspecified);
}
else if (FLOW_ELE.equals(name)) {
boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement);
parseFlow(stepElement, nestedElement, bd, parserContext, stepUnderspecified);
}
else if (PARTITION_ELE.equals(name)) {
boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement);
parsePartition(stepElement, nestedElement, bd, parserContext, stepUnderspecified, jobFactoryRef);
}
else if (JOB_ELE.equals(name)) {
boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement);
parseJob(stepElement, nestedElement, bd, parserContext, stepUnderspecified);
}
else if ("description".equals(name)) {
bd.setDescription(nestedElement.getTextContent());
}
// nested bean reference/declaration
else {
String ns = nestedElement.getNamespaceURI();
Object value = null;
boolean skip = false;
// Spring NS
if ((ns == null && name.equals(BeanDefinitionParserDelegate.BEAN_ELEMENT))
|| ns.equals(BeanDefinitionParserDelegate.BEANS_NAMESPACE_URI)) {
BeanDefinitionHolder holder = parserContext.getDelegate()
.parseBeanDefinitionElement(nestedElement);
value = parserContext.getDelegate().decorateBeanDefinitionIfRequired(nestedElement, holder);
}
// Spring Batch transitions
else if (ns.equals("http://www.springframework.org/schema/batch")) {
// don't parse
skip = true;
}
// Custom NS
else {
value = parserContext.getDelegate().parseCustomElement(nestedElement);
}
if (!skip) {
bd.setBeanClass(StepParserStepFactoryBean.class);
bd.setAttribute("isNamespaceStep", true);
builder.addPropertyValue("tasklet", value);
}
}
}
}
String parentRef = stepElement.getAttribute(PARENT_ATTR);
if (StringUtils.hasText(parentRef)) {
bd.setParentName(parentRef);
}
String isAbstract = stepElement.getAttribute("abstract");
if (StringUtils.hasText(isAbstract)) {
bd.setAbstract(Boolean.valueOf(isAbstract));
}
String jobRepositoryRef = stepElement.getAttribute(JOB_REPO_ATTR);
if (StringUtils.hasText(jobRepositoryRef)) {
builder.addPropertyReference("jobRepository", jobRepositoryRef);
}
if (StringUtils.hasText(jobFactoryRef)) {
bd.setAttribute("jobParserJobFactoryBeanRef", jobFactoryRef);
}
// add the allow parser here
String isAllowStart = stepElement.getAttribute(ALLOW_START_ATTR);
if (StringUtils.hasText(isAllowStart)) {
// check if the value is already set from an inner element
if (!bd.getPropertyValues().contains("allowStartIfComplete")) {
// set the value as a property
bd.getPropertyValues().add("allowStartIfComplete", Boolean.valueOf(isAllowStart));
} // end if
}
stepListenerParser.handleListenersElement(stepElement, bd, parserContext);
return bd;
}
private void parsePartition(Element stepElement, Element partitionElement, AbstractBeanDefinition bd,
ParserContext parserContext, boolean stepUnderspecified, String jobFactoryRef) {
bd.setBeanClass(StepParserStepFactoryBean.class);
bd.setAttribute("isNamespaceStep", true);
String stepRef = partitionElement.getAttribute(STEP_ATTR);
String partitionerRef = partitionElement.getAttribute(PARTITIONER_ATTR);
String aggregatorRef = partitionElement.getAttribute(AGGREGATOR_ATTR);
String handlerRef = partitionElement.getAttribute(HANDLER_ATTR);
if (!StringUtils.hasText(partitionerRef)) {
parserContext.getReaderContext().error("You must specify a partitioner", partitionElement);
return;
}
MutablePropertyValues propertyValues = bd.getPropertyValues();
propertyValues.addPropertyValue("partitioner", new RuntimeBeanReference(partitionerRef));
if (StringUtils.hasText(aggregatorRef)) {
propertyValues.addPropertyValue("stepExecutionAggregator", new RuntimeBeanReference(aggregatorRef));
}
boolean customHandler = false;
if (!StringUtils.hasText(handlerRef)) {
Element handlerElement = DomUtils.getChildElementByTagName(partitionElement, HANDLER_ELE);
if (handlerElement != null) {
String taskExecutorRef = handlerElement.getAttribute(TASK_EXECUTOR_ATTR);
if (StringUtils.hasText(taskExecutorRef)) {
propertyValues.addPropertyValue("taskExecutor", new RuntimeBeanReference(taskExecutorRef));
}
String gridSize = handlerElement.getAttribute(GRID_SIZE_ATTR);
if (StringUtils.hasText(gridSize)) {
propertyValues.addPropertyValue("gridSize", new TypedStringValue(gridSize));
}
}
}
else {
customHandler = true;
BeanDefinition partitionHandler = BeanDefinitionBuilder.genericBeanDefinition().getRawBeanDefinition();
partitionHandler.setParentName(handlerRef);
propertyValues.addPropertyValue("partitionHandler", partitionHandler);
}
Element inlineStepElement = DomUtils.getChildElementByTagName(partitionElement, STEP_ELE);
if (inlineStepElement == null && !StringUtils.hasText(stepRef) && !customHandler) {
parserContext.getReaderContext().error("You must specify a step", partitionElement);
return;
}
if (StringUtils.hasText(stepRef)) {
propertyValues.addPropertyValue("step", new RuntimeBeanReference(stepRef));
}
else if (inlineStepElement != null) {
AbstractBeanDefinition stepDefinition = parseStep(inlineStepElement, parserContext, jobFactoryRef);
stepDefinition.getPropertyValues().addPropertyValue("name", stepElement.getAttribute(ID_ATTR));
propertyValues.addPropertyValue("step", stepDefinition);
}
}
private void parseJob(Element stepElement, Element jobElement, AbstractBeanDefinition bd,
ParserContext parserContext, boolean stepUnderspecified) {
bd.setBeanClass(StepParserStepFactoryBean.class);
bd.setAttribute("isNamespaceStep", true);
String jobRef = jobElement.getAttribute(REF_ATTR);
if (!StringUtils.hasText(jobRef)) {
parserContext.getReaderContext().error("You must specify a job", jobElement);
return;
}
MutablePropertyValues propertyValues = bd.getPropertyValues();
propertyValues.addPropertyValue("job", new RuntimeBeanReference(jobRef));
String jobParametersExtractor = jobElement.getAttribute(JOB_PARAMS_EXTRACTOR_ATTR);
String jobLauncher = jobElement.getAttribute(JOB_LAUNCHER_ATTR);
if (StringUtils.hasText(jobParametersExtractor)) {
propertyValues.addPropertyValue("jobParametersExtractor", new RuntimeBeanReference(jobParametersExtractor));
}
if (StringUtils.hasText(jobLauncher)) {
propertyValues.addPropertyValue("jobLauncher", new RuntimeBeanReference(jobLauncher));
}
}
private void parseFlow(Element stepElement, Element flowElement, AbstractBeanDefinition bd,
ParserContext parserContext, boolean stepUnderspecified) {
bd.setBeanClass(StepParserStepFactoryBean.class);
bd.setAttribute("isNamespaceStep", true);
String flowRef = flowElement.getAttribute(PARENT_ATTR);
String idAttribute = stepElement.getAttribute(ID_ATTR);
BeanDefinition flowDefinition = new GenericBeanDefinition();
flowDefinition.setParentName(flowRef);
MutablePropertyValues propertyValues = flowDefinition.getPropertyValues();
if (StringUtils.hasText(idAttribute)) {
propertyValues.addPropertyValue("name", idAttribute);
}
bd.getPropertyValues().addPropertyValue("flow", flowDefinition);
}
}
相关信息
相关文章
spring-batch AbstractFlowParser 源码
spring-batch AbstractListenerParser 源码
spring-batch BeanDefinitionUtils 源码
spring-batch ChunkElementParser 源码
spring-batch CoreNamespaceHandler 源码
spring-batch CoreNamespacePostProcessor 源码
spring-batch CoreNamespaceUtils 源码
spring-batch DecisionParser 源码
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦