>  기사  >  Java  >  Java에서 Spring 구성 태그를 사용자 정의하는 방법

Java에서 Spring 구성 태그를 사용자 정의하는 방법

WBOY
WBOY앞으로
2023-04-24 17:16:171366검색

소개:

Spring에서 과 같은 요소는 일반적으로 Bean을 구성하는 데 사용됩니다. Spring은 컨테이너를 생성할 때 이러한 구성을 검색하고 구성을 기반으로 객체를 생성한 다음 이를 컨테이너에 저장합니다. 컨테이너에서 꺼내거나 다른 Bean을 구성할 때 속성으로 삽입합니다. Bean 구성 사용의 한 가지 제한사항은 구성 파일의 XML 스키마 정의를 따라야 한다는 것인데, 이는 대부분의 경우 문제가 되지 않습니다. 그러나 어떤 경우에는 보다 유연한 Bean 구성을 원합니다. Spring은 이를 위해 확장 가능한 XML 작성이라고도 알려진 사용자 정의 태그 지원을 제공합니다. 이 확장 지점을 통해 필요한 구성 형식을 유연하게 사용자 정의할 수 있습니다.

예를 들어, 애플리케이션을 설계하기 위해 책임 체인을 사용하는 경우 다음과 같은 방식으로 책임 체인을 구성할 수 있습니다.

<chain id="orderChain" class="foo.bar">
    <handler> handler1</handler>
    <hadnler> handler2</handler>
</chain>

Spring이 컨테이너를 생성할 때 해당 요소가 스캔될 때, 이전 정의에 따라 구성됩니다. 정의는 책임 개체 체인을 인스턴스화하고 속성을 채웁니다. 따라서 이 특수 태그는 태그 대신 사용할 수 있습니다. Spring의 Custom Tag를 사용하면 이러한 Bean 구성을 완벽하게 구현할 수 있습니다. 제품 수준 애플리케이션 프레임워크에서는 더 복잡한 사용자 정의 라벨 요소를 구현할 수 있습니다. 초급 수준 소개로 날짜 형식 지정을 구성하기 위한 SimpleDateFormat 클래스를 정의합니다. 물론 전통적인 을 사용하는 것만으로도 충분합니다. 여기서는 단지 예일 뿐입니다.

HelloWorld 예:

태그 사용자 정의의 첫 번째 단계는 태그 요소의 XML 구조를 정의하는 것입니다. 이는 XSD를 사용하여 사용자 정의하려는 요소의 구조를 요소화할 때 나타나는 모습입니다.

간단한 XSD를 다음과 같이 정의합니다.

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.mycompany.com/schema/myns"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:beans="http://www.springframework.org/schema/beans"
        targetNamespace="http://www.mycompany.com/schema/myns"
        elementFormDefault="qualified"
        attributeFormDefault="unqualified">
 
    <xsd:import namespace="http://www.springframework.org/schema/beans"/>
 
    <xsd:element name="dateformat">
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="beans:identifiedType">
                    <xsd:attribute name="lenient" type="xsd:boolean"/>
                    <xsd:attribute name="pattern" type="xsd:string" use="required"/>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

이 XSD 정의에는 bean 태그를 대체하는 데 사용하는 사용자 정의 태그인 dateformat이라는 태그가 있습니다. Spring의 자체 bean 네임스페이스를 가져오고 beans:identifiedType을 기반으로 dateformat 태그를 정의했습니다. 즉, 태그는 태그와 같은 id 속성을 가질 수 있습니다. 동시에 관대함과 패턴이라는 두 가지 속성을 추가했습니다. 이것은 약간 상속과 같은 느낌이 듭니다.

XSD를 정의한 후 Spring에 이러한 태그(네임스페이스 + 요소 이름)가 나타나면 객체 생성 방법을 알려주어야 합니다. Spring에서는 NamespaceHandler가 이 작업을 수행하는 데 사용됩니다. 따라서 사용자 정의 태그 요소를 처리하려면 NamespaceHandler 구현을 제공해야 합니다.

간단한 구현은 다음과 같습니다.

package extensiblexml.customtag;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class MyNamespaceHandler extends NamespaceHandlerSupport {
	public void init() {
		registerBeanDefinitionParser("dateformat",
				new SimpleDateFormatBeanDefinitionParser());
	}
 
}

초기화 방법에 Bean 정의 파서를 등록했습니다. 이 파서는 사용자 정의된 구성 태그를 파싱하는 데 사용됩니다.

구현은 다음과 같습니다.

package extensiblexml.customtag;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
import java.text.SimpleDateFormat;
public class SimpleDateFormatBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { 
    protected Class<SimpleDateFormat> getBeanClass(Element element) {
        return SimpleDateFormat.class; 
    }
    @SuppressWarnings("deprecation")
	protected void doParse(Element element, BeanDefinitionBuilder bean) {
        // this will never be null since the schema explicitly requires that a value be supplied
        String pattern = element.getAttribute("pattern");
        bean.addConstructorArg(pattern);
 
        // this however is an optional property
        String lenient = element.getAttribute("lenient");
        if (StringUtils.hasText(lenient)) {
            bean.addPropertyValue("lenient", Boolean.valueOf(lenient));
        }
    }
 
}

이 파서의 doParse는 Spring에서 제공하는 지원 클래스를 사용하여 파싱을 쉽게 완료할 수 있습니다. 위의 세 파일은 동일한 디렉터리에 위치합니다. 즉, XSD 파일과 Java 코드가 동일한 디렉터리에 위치합니다. 코딩이 완료된 후에도 일부 구성 작업을 수행해야 합니다. 우리는 사용자 정의 태그 요소를 사용할 것이라고 Spring에게 알려주고 요소를 구문 분석하는 방법을 Spring에게 알려야 합니다. 그렇지 않으면 Spring은 그다지 똑똑하지 않습니다. 여기에는 두 개의 구성 파일이 필요합니다. 코드 루트 경로와 동일한 수준에 매트리스에는 META-INF라는 파일이 있습니다. 그리고 내부에 spring.handlers 및 spring.schemas라는 클래스를 생성합니다. 이 클래스는 Spring에게 사용자 정의 태그의 문서 구조와 이를 구문 분석하는 클래스를 알려주는 데 사용됩니다. 두 파일의 내용은 다음과 같습니다.

spring.handlers:

http://www.mycompany.com/schema/myns=extensiblexml.customtag.MyNamespaceHandler

왼쪽 등호 XSD 정의 속성의 targetNamespace이고 오른쪽은 NamespaceHandler의 정규화된 이름입니다.

spring.schemas:

http://www.mycompany.com/schema/myns/myns.xsd=extensiblexml/customtag/myns.xsd

그런 다음 Bean을 평소와 같이 간단하게 구성합니다. 테스트, 빈을 정의합니다:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:myns="http://www.mycompany.com/schema/myns"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.mycompany.com/schema/myns http://www.mycompany.com/schema/myns/myns.xsd" >
 
	<myns:dateformat id="defaultDateFormat" pattern="yyyy-MM-dd HH:mm"
		lenient="true" />
</beans>

Eclipse에서 전체 프로젝트 구조는 다음과 같습니다:

Java에서 Spring 구성 태그를 사용자 정의하는 방법

마지막으로 작동 가능한지 테스트하기 위해 테스트 클래스를 작성합니다.

package extensiblexml.customtag;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext(
				"beans.xml");
		SimpleDateFormat format = (SimpleDateFormat) context
				.getBean("defaultDateFormat");
		System.out.println(format.format(new Date()));
 
	}
 
}

Everything 다음과 같이 출력됩니다.

Java에서 Spring 구성 태그를 사용자 정의하는 방법

더 많은 실제 예제

첫 번째 예제는 주로 설명을 위한 것이며 실제로는 별로 유용하지 않습니다. 더 복잡한 사용자 정의 태그를 살펴보겠습니다. Spring이 이 태그를 스캔하면 지정된 디렉토리에 File 클래스 컬렉션이 생성됩니다. 또한 를 사용하여 이 디렉터리의 파일을 필터링할 수 있습니다.

다음과 같습니다:

<core-commons:fileList id="xmlList" directory="src/extensiblexml/example">
    <core-commons:fileFilter>
	<bean class="org.apache.commons.io.filefilter.RegexFileFilter">
	    <constructor-arg value=".*.java" />
	</bean>
    </core-commons:fileFilter>
</core-commons:fileList>

위의 Bean 정의에서는 "src/extensible/example" 디렉터리에서 Java 소스 코드 파일을 필터링합니다.

다음 테스트 반복 출력 파일 이름을 사용하세요.

@SuppressWarnings("unchecked")
List<File> fileList = (List<File>) context.getBean("xmlList");
for (File file : fileList) {
	System.out.println(file.getName());
}

输出结果如下:

Java에서 Spring 구성 태그를 사용자 정의하는 방법

根据第一个例子中的步骤,各部分配置及代码如下:

core-commons-1.0.xsd:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.example.com/schema/core-commons-1.0"
	targetNamespace="http://www.example.com/schema/core-commons-1.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	xmlns:beans="http://www.springframework.org/schema/beans"
	elementFormDefault="qualified"
	attributeFormDefault="unqualified"
	version="1.0">
 
	<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"/>
 
    <xsd:element name="fileList">
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="beans:identifiedType">
                    <xsd:sequence>
                        <xsd:element ref="fileFilter" minOccurs="0" maxOccurs="1"/>
                        <xsd:element ref="fileList" minOccurs="0" maxOccurs="unbounded"/>
                    </xsd:sequence>
                    <xsd:attribute name="directory" type="xsd:string"/>
                    <xsd:attribute name="scope" type="xsd:string"/>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>
 
    <xsd:element name="fileFilter">
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="beans:identifiedType">
                    <xsd:group ref="limitedType"/>
                    <xsd:attribute name="scope" type="xsd:string"/>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>
 
    <xsd:group name="limitedType">
        <xsd:sequence>
            <xsd:choice minOccurs="1" maxOccurs="unbounded">
                <xsd:element ref="beans:bean"/>
                <xsd:element ref="beans:ref"/>
                <xsd:element ref="beans:idref"/>
                <xsd:element ref="beans:value"/>
                <xsd:any minOccurs="0"/>
            </xsd:choice>
        </xsd:sequence>
    </xsd:group>
</xsd:schema>

CoreNamespaceHandler.java:

package extensiblexml.example;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class CoreNamespaceHandler
    extends NamespaceHandlerSupport
{
    @Override
    public void init() {
        this.registerBeanDefinitionParser("fileList", new FileListDefinitionParser());
        this.registerBeanDefinitionParser("fileFilter", new FileFilterDefinitionParser());
    }
}

FileListDefinitionParser.java:

public class FileListDefinitionParser
	extends AbstractSingleBeanDefinitionParser
{
	/**
	 * The bean that is created for this tag element
	 *
	 * @param element The tag element
	 * @return A FileListFactoryBean
	 */
	@Override
	protected Class<?> getBeanClass(Element element) {
		return FileListFactoryBean.class;
	}
 
	/**
	 * Called when the fileList tag is to be parsed
	 *
	 * @param element The tag element
	 * @param ctx The context in which the parsing is occuring
	 * @param builder The bean definitions build to use
	 */
	@Override
	protected void doParse(Element element, ParserContext ctx, BeanDefinitionBuilder builder) {
		// Set the directory property
		builder.addPropertyValue("directory", element.getAttribute("directory"));
 
		// Set the scope
		builder.setScope(element.getAttribute("scope"));
 
		// We want any parsing to occur as a child of this tag so we need to make
		// a new one that has this as it&#39;s owner/parent
		ParserContext nestedCtx = new ParserContext(ctx.getReaderContext(), ctx.getDelegate(), builder.getBeanDefinition());
 
		// Support for filters
		Element exclusionElem = DomUtils.getChildElementByTagName(element, "fileFilter");
		if (exclusionElem != null) {
			// Just make a new Parser for each one and let the parser do the work
			FileFilterDefinitionParser ff = new FileFilterDefinitionParser();
			builder.addPropertyValue("filters", ff.parse(exclusionElem, nestedCtx));
		}
 
		// Support for nested fileList
		List<Element> fileLists = DomUtils.getChildElementsByTagName(element, "fileList");
		// Any objects that created will be placed in a ManagedList
		// so Spring does the bulk of the resolution work for us
		ManagedList<Object> nestedFiles = new ManagedList<Object>();
		if (fileLists.size() > 0) {
			// Just make a new Parser for each one and let them do the work
			FileListDefinitionParser fldp = new FileListDefinitionParser();
			for (Element fileListElem : fileLists) {
				nestedFiles.add(fldp.parse(fileListElem, nestedCtx));
			}
		}
 
		// Support for other tags that return File (value will be converted to file)
		try {
			// Go through any other tags we may find.  This does not mean we support
			// any tag, we support only what parseLimitedList will process
			NodeList nl = element.getChildNodes();
			for (int i=0; i<nl.getLength(); i++) {
				// Parse each child tag we find in the correct scope but we
				// won&#39;t support custom tags at this point as it coudl destablize things
				DefinitionParserUtil.parseLimitedList(nestedFiles, nl.item(i), ctx,
					builder.getBeanDefinition(), element.getAttribute("scope"), false);
			}
		}
		catch (Exception e) {
			throw new RuntimeException(e);
		}
 
		// Set the nestedFiles in the properties so it is set on the FactoryBean
		builder.addPropertyValue("nestedFiles", nestedFiles);
 
	}
 
	public static class FileListFactoryBean
		implements FactoryBean<Collection<File>>
	{
 
		String directory;
		private Collection<FileFilter> filters;
		private Collection<File> nestedFiles;
 
		@Override
		public Collection<File> getObject() throws Exception {
			// These can be an array list because the directory will have unique&#39;s and the nested is already only unique&#39;s
			Collection<File> files = new ArrayList<File>();
			Collection<File> results = new ArrayList<File>(0);
 
			if (directory != null) {
				// get all the files in the directory
				File dir = new File(directory);
				File[] dirFiles = dir.listFiles();
				if (dirFiles != null) {
					files = Arrays.asList(dirFiles);
				}
			}
 
			// If there are any files that were created from the nested tags,
			// add those to the list of files
			if (nestedFiles != null) {
				files.addAll(nestedFiles);
			}
 
			// If there are filters we need to go through each filter
			// and see if the files in the list pass the filters.
			// If the files does not pass any one of the filters then it
			// will not be included in the list
			if (filters != null) {
				boolean add;
				for (File f : files) {
					add = true;
					for (FileFilter ff : filters) {
						if (!ff.accept(f)) {
							add = false;
							break;
						}
					}
					if (add) results.add(f);
				}
				return results;
			}
 
			return files;
		}
 
		@Override
		public Class<?> getObjectType() {
			return Collection.class;
		}
 
		@Override
		public boolean isSingleton() {
			return false;
		}
 
		public void setDirectory(String dir) {
			this.directory = dir;
		}
		public void setFilters(Collection<FileFilter> filters) {
			this.filters = filters;
		}
 
		/**
		 * What we actually get from the processing of the nested tags
		 * is a collection of files within a collection so we flatten it and
		 * only keep the uniques
		 */
		public void setNestedFiles(Collection<Collection<File>> nestedFiles) {
			this.nestedFiles = new HashSet<File>(); // keep the list unique
			for (Collection<File> nested : nestedFiles) {
				this.nestedFiles.addAll(nested);
			}
		}
 
	}
}

FileFilterDefinitionParser.java

public class FileFilterDefinitionParser
	extends AbstractSingleBeanDefinitionParser
{
 
	/**
	 * The bean that is created for this tag element
	 *
	 * @param element The tag element
	 * @return A FileFilterFactoryBean
	 */
	@Override
	protected Class<?> getBeanClass(Element element) {
		return FileFilterFactoryBean.class;
	}
 
	/**
	 * Called when the fileFilter tag is to be parsed
	 *
	 * @param element The tag element
	 * @param ctx The context in which the parsing is occuring
	 * @param builder The bean definitions build to use
	 */
	@Override
	protected void doParse(Element element, ParserContext ctx, BeanDefinitionBuilder builder) {
 
		// Set the scope
		builder.setScope(element.getAttribute("scope"));
 
		try {
			// All of the filters will eventually end up in this list
			// We use a &#39;ManagedList&#39; and not a regular list because anything
			// placed in a ManagedList object will support all of Springs
			// functionalities and scopes for us, we dont&#39; have to code anything
			// in terms of reference lookups, EL, etc
			ManagedList<Object> filters = new ManagedList<Object>();
 
			// For each child node of the fileFilter tag, parse it and place it
			// in the filtes list
			NodeList nl = element.getChildNodes();
			for (int i=0; i<nl.getLength(); i++) {
				DefinitionParserUtil.parseLimitedList(filters, nl.item(i), ctx, builder.getBeanDefinition(), element.getAttribute("scope"));
			}
 
			// Add the filtes to the list of properties (this is applied
			// to the factory beans setFilters below)
			builder.addPropertyValue("filters", filters);
		}
		catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
 
	public static class FileFilterFactoryBean
		implements FactoryBean<Collection<FileFilter>>
	{
 
		private final List<FileFilter> filters = new ArrayList<FileFilter>();
 
		@Override
		public Collection<FileFilter> getObject() throws Exception {
			return filters;
		}
 
		@Override
		public Class<?> getObjectType() {
			return Collection.class;
		}
 
		@Override
		public boolean isSingleton() {
			return false;
		}
 
		/**
		 * Go through the list of filters and convert the String ones
		 * (the ones that were set with <value> and make them NameFileFilters
		 */
		public void setFilters(Collection<Object> filterList) {
			for (Object o : filterList) {
				if (o instanceof String) {
					filters.add(new NameFileFilter(o.toString()));
				}
				else if (o instanceof FileFilter) {
					filters.add((FileFilter)o);
				}
			}
		}
 
	}
}

DefinitionParserUtil.java:

package extensiblexml.example;
 
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
 
public class DefinitionParserUtil {
 
	/**
	 * Parses the children of the passed in ParentNode for the following tags:
	 * <br/>
	 * value
	 * ref
	 * idref
	 * bean
	 * property
	 * *custom*
	 * <p/>
	 *
	 * The value tag works with Spring EL even in a Spring Batch scope="step"
	 *
	 * @param objects The list of resultings objects from the parsing (passed in for recursion purposes)
	 * @param parentNode The node who&#39;s children should be parsed
	 * @param ctx The ParserContext to use
	 * @param parentBean The BeanDefinition of the bean who is the parent of the parsed bean
	 * 		(i.e. the Bean that is the parentNode)
	 * @param scope The scope to execute in.  Checked if &#39;step&#39; to provide Spring EL
	 * 		support in a Spring Batch env
	 * @throws Exception
	 */
	public static void parseLimitedList(ManagedList<Object> objects, Node node,
		ParserContext ctx, BeanDefinition parentBean, String scope)
		throws Exception
	{
		parseLimitedList(objects, node, ctx, parentBean, scope, true);
	}
 
	/**
	 * Parses the children of the passed in ParentNode for the following tags:
	 * <br/>
	 * value
	 * ref
	 * idref
	 * bean
	 * property
	 * *custom*
	 * <p/>
	 *
	 * The value tag works with Spring EL even in a Spring Batch scope="step"
	 *
	 * @param objects The list of resultings objects from the parsing (passed in for recursion purposes)
	 * @param parentNode The node who&#39;s children should be parsed
	 * @param ctx The ParserContext to use
	 * @param parentBean The BeanDefinition of the bean who is the parent of the parsed bean
	 * 		(i.e. the Bean that is the parentNode)
	 * @param scope The scope to execute in.  Checked if &#39;step&#39; to provide Spring EL
	 * 		support in a Spring Batch env
	 * @param supportCustomTags Should we support custom tags within our tags?
	 * @throws Exception
	 */
	@SuppressWarnings("deprecation")
	public static void parseLimitedList(ManagedList<Object> objects, Node node,
		ParserContext ctx, BeanDefinition parentBean, String scope, boolean supportCustomTags)
		throws Exception
	{
		// Only worry about element nodes
		if (node.getNodeType() == Node.ELEMENT_NODE) {
			Element elem = (Element)node;
			String tagName = node.getLocalName();
 
			if (tagName.equals("value")) {
				String val = node.getTextContent();
				// to get around an issue with Spring Batch not parsing Spring EL
				// we will do it for them
				if (scope.equals("step")
					&& (val.startsWith("#{") && val.endsWith("}"))
					&& (!val.startsWith("#{jobParameters"))
					)
				{
					// Set up a new EL parser
					ExpressionParser parser = new SpelExpressionParser();
					// Parse the value
					Expression exp = parser.parseExpression(val.substring(2, val.length()-1));
					// Place the results in the list of created objects
					objects.add(exp.getValue());
				}
				else {
					// Otherwise, just treat it as a normal value tag
					objects.add(val);
				}
			}
			// Either of these is a just a lookup of an existing bean
			else if (tagName.equals("ref") || tagName.equals("idref")) {
				objects.add(ctx.getRegistry().getBeanDefinition(node.getTextContent()));
			}
			// We need to create the bean
			else if (tagName.equals("bean")) {
				// There is no quick little util I could find to create a bean
				// on the fly programmatically in Spring and still support all
				// Spring functionality so basically I mimic what Spring actually
				// does but on a smaller scale.  Everything Spring allows is
				// still supported
 
				// Create a factory to make the bean
				DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
				// Set up a parser for the bean
				BeanDefinitionParserDelegate pd = new BeanDefinitionParserDelegate(ctx.getReaderContext());
				// Parse the bean get its information, now in a DefintionHolder
				BeanDefinitionHolder bh = pd.parseBeanDefinitionElement(elem, parentBean);
				// Register the bean will all the other beans Spring is aware of
				BeanDefinitionReaderUtils.registerBeanDefinition(bh, beanFactory);
				// Get the bean from the factory.  This will allows Spring
				// to do all its work (EL processing, scope, etc) and give us
				// the actual bean itself
				Object bean = beanFactory.getBean(bh.getBeanName());
				objects.add(bean);
			}
			/*
			 * This is handled a bit differently in that it actually sets the property
			 * on the parent bean for us based on the property
			 */
			else if (tagName.equals("property")) {
				BeanDefinitionParserDelegate pd = new BeanDefinitionParserDelegate(ctx.getReaderContext());
				// This method actually set eh property on the parentBean for us so
				// we don&#39;t have to add anything to the objects object
				pd.parsePropertyElement(elem, parentBean);
			}
			else if (supportCustomTags) {
				// handle custom tag
				BeanDefinitionParserDelegate pd = new BeanDefinitionParserDelegate(ctx.getReaderContext());
				BeanDefinition bd = pd.parseCustomElement(elem, parentBean);
				objects.add(bd);
			}
		}
	}
}

spring.schemas

http\://www.mycompany.com/schema/myns/myns.xsd=extensiblexml/customtag/myns.xsd
http\://www.example.com/schema/core-commons-1.0.xsd=extensiblexml/example/core-commons-1.0.xsd

spring.handlers

http\://www.mycompany.com/schema/myns=extensiblexml.customtag.MyNamespaceHandler
http\://www.example.com/schema/core-commons-1.0=extensiblexml.example.CoreNamespaceHandler

小结:

要自定义Spring的配置标签,需要一下几个步骤:

  • 使用XSD定义XML配置中标签元素的结构(myns.XSD)

  • 提供该XSD命名空间的处理类,它可以处理多个标签定义(MyNamespaceHandler.java)

  • 为每个标签元素的定义提供解析类。(SimpleDateFormatBeanDefinitionParser.java)

  • 两个特殊文件通知Spring使用自定义标签元素(spring.handlers 和spring.schemas)

위 내용은 Java에서 Spring 구성 태그를 사용자 정의하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제