`
0428loveyu
  • 浏览: 30773 次
  • 性别: Icon_minigender_2
  • 来自: 西安
文章分类
社区版块
存档分类
最新评论

自定义Spring配置标签

 
阅读更多

引言:

在Sping中,一般使用<bean>这样的元素来配置一个bean,Spring在创建容器的时候会扫描这些配置,根据配置创建对象存放于容器中,然后我们再从容器中取出,或者在配置其他bean的时候作为属性注入。使用bean配置的一个限制是我们必须遵循配置文件的XML Schema定义,这在大多数情况下不会出现问题。但是在一些情况下,我们希望实现更为灵活的bean配置。Spring为此提供了 Custom tag Support,也称为Extensible XMLAuthoring。通过这个拓展点,我们可以灵活定制自己需要的配置格式。


例如,如果我们使用了责任链设计应用程序,那么我们可能希望用下面的方式来配置责任链:

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

档Spring创建容器时,扫描到这样的元素的时候,会根据我们事先的定义实例化一个责任链对象,并填充属性。因此,这种特殊的<chain>标签可以作为<bean>标签以外的另一种形式。借助Spring的Custome Tag,我们完全可以实现这样的bean配置。在产品级的应用框架中,可以实现更为复杂的定制标签元素。作为一个入门级别的介绍,我们定义一个用于配置日期格式化的一个类SimpleDateFormat。当然,使用传统的<bean>完全够用,我们这里只是作为例子。


一个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定义中,有一个标签叫dateformat,这就是我们用来替换bean标签的自定义标签。注意到我们导入了Spring本身的beans命名空间,并且在beans:identifiedType基础之上定义dateformat标签。也就是我们这个标签可以像<bean>标签一样拥有id属性。同时我们增加了两个属性lenient和pattern。这有点继承的味道。


定义完XSD之后,我们要告诉Spring遇到这样的标记(命名空间+元素名称)时,如何创建对象。Spring中,完成这个任务的是NamespaceHandler。因此我们需要提供一个NamespaceHandler实现来处理自定义的<dateformat>标签元素。一个简单的实现如下:

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没那么聪明。这里需要2个配置文件,在与代码根路径同一级别下,床垫一个叫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,作为简单的测试,我们定义一个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中,整个项目结构如下图:



最后我们写个测试类测试一下能否工作:

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()));

	}

}

一切正常,输出如下:



更实用的例子

第一个例子主要是为了举例,在实际中用处不大,我们接着来看一个更复杂的自定义标签。我们自定义一个<fileList>标签,当Spring扫描到这个标签的时候,创建一个指定目录下的File类的集合。另外,可以使用<fileFilter>对该目录的文件进行过滤。如下:

<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());
}
输出结果如下:


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

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'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'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's and the nested is already only unique'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 'ManagedList' and not a regular list because anything
			// placed in a ManagedList object will support all of Springs
			// functionalities and scopes for us, we dont' 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'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 'step' 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'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 'step' 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'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)


参考资料:

Spring官方的Extensible XML Authoring文档:

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/extensible-xml.html

一个不错的教程:

http://sloanseaman.com/wordpress/2012/03/26/spring-custom-tags-extensible-xml-part-1/

http://sloanseaman.com/wordpress/2012/04/08/spring-custom-tags-extensible-xml-part-2/


转载请注明出处。



分享到:
评论

相关推荐

    spring自定义标签例子

    通过研究这个例子,我们可以学习到如何将业务逻辑抽象出来,封装成自定义标签,使Spring配置更加简洁。这对于大型项目来说尤其重要,因为它可以提高代码的可读性和模块化程度。 此外,理解自定义标签的工作原理还能...

    spring 自定义xml标签

    总之,自定义Spring XML标签是一项强大的功能,它允许开发者按照项目特性定制配置语法,提高代码的可读性和可维护性。通过实现`NamespaceHandler`和`BeanDefinitionParser`,我们可以轻松地将业务逻辑融入到Spring的...

    Spring自定义配置文件便签[Maven]工程可运行

    在Spring框架中,自定义配置文件和标签是提高代码可读性和灵活性的重要手段。这个名为"Spring自定义配置文件便签[Maven]工程可运行"的项目,显然是一个基于Maven构建的Spring 5.0应用程序,它包含了自定义配置文件和...

    spring-boot 自定义xml配置web请求拦截器

    自定义XML配置通常会涉及到Spring的`&lt;beans&gt;`标签和`&lt;bean&gt;`标签,用于声明和实例化对象。在XML中定义拦截器,我们需要创建一个实现了`HandlerInterceptor`接口的类,并在XML配置文件中声明这个类。然后,我们可以...

    spring mvc freemarker 自定义标签

    然后,你需要在Spring配置中注册这个自定义标签。在`WebMvcConfigurer`的实现中,添加`freemarkerConfiguration` bean,并使用`freemarkerConfigurer`的`setCustomTags`方法添加自定义标签: ```java @...

    Spring 5.2.9 06 源码分析-spring自定义标签解析过程

    在Spring框架中,自定义标签解析是扩展Spring配置能力的重要方式。通过自定义标签,开发者可以创建更加符合业务逻辑和可读性强的XML配置文件。本文将深入剖析Spring 5.2.9版本中自定义标签的解析过程,旨在帮助读者...

    spring自定义标签

    在Spring框架中,自定义标签是一项非常实用的功能,它允许我们创建自己的XML标签来简化配置,提高代码可读性,并实现特定的业务逻辑。本文将深入探讨Spring自定义标签的概念、实现过程及其在实际开发中的应用。 ...

    自定义 Schema 解析 Spring Bean

    通过定义自定义Schema,我们可以限制或扩展Spring配置文件中可用的元素和属性,确保配置的正确性和一致性。 实现自定义Schema解析的过程主要包括以下几个步骤: 1. **定义Schema**: 使用XSD(XML Schema ...

    spring-扩展点-namespacehandler(Spring自定义标签)

    当我们需要在Spring配置文件中引入自定义标签时,`NamespaceHandler`起着至关重要的作用。这篇博文通过分析`spring-web-namespacehandler`,将深入探讨这一主题。 首先,`NamespaceHandler`是Spring框架解析XML配置...

    06 源码分析-spring自定义标签解析过程

    在Spring框架中,自定义标签的解析过程是一个关键的组件,它使得开发者能够通过XML配置文件以更加直观和简洁的方式声明Bean的定义。本节将深入探讨Spring 5.2.9版本中自定义标签的解析机制,以及背后的源码实现。 ...

    这一次搞懂Spring自定义标签以及注解解析原理说明

    在Spring框架中,自定义标签和注解解析是两个关键的特性,它们使得代码与配置的集成更加紧密,简化了应用程序的开发。本篇文章将深入探讨Spring如何处理这两种类型的元数据。 首先,让我们来理解Spring如何解析...

    这一次搞懂Spring自定义标签以及注解解析原理说明.docx

    在Spring框架中,自定义标签和注解解析是核心功能之一,它们允许开发者根据特定需求扩展和定制Spring的配置方式。本文将深入探讨这两个概念的解析原理,帮助读者理解Spring如何处理自定义标签和注解。 首先,让我们...

    SpringBoot中自定义日志配置logback-spring.xml示例源码

    本教程将详细介绍如何在Spring Boot中自定义日志配置,特别是通过`logback-spring.xml`文件来实现。 首先,我们需要理解`logback-spring.xml`与传统的`logback.xml`的区别。`logback-spring.xml`是专门为Spring ...

    spring 自定义属性编辑器

    - 配置文件注册:在Spring的XML配置文件中,通过`&lt;bean&gt;`标签的`property-editorRegistrar`属性指定一个实现了`PropertyEditorRegistrar`接口的类。在该类的`registerEditors()`方法中,可以使用`...

    自定义分页标签struts2,spring

    本项目"自定义分页标签struts2,spring"是针对Struts2和Spring框架的一个自定义标签实现,旨在简化开发过程,提高代码的可复用性和可维护性。下面我们将详细探讨这个项目中的关键技术点。 首先,Struts2是一个非常...

    自定义xml标签

    在Spring框架中,自定义XML标签是扩展Spring配置能力的一种方式,这允许我们创建更加语义化的配置元素,提高代码的可读性和可维护性。本文将深入探讨如何结合Spring来实现自定义XML标签,并利用FactoryBean进行代理...

    SpringSecurity 之自定义用户权限信息的存取

    本文将详细探讨SpringSecurity中关于自定义用户权限信息存取的实现方法,包括如何通过配置文件和数据库来管理用户的认证信息和权限数据。 首先,当我们谈论用户权限信息的存取,实际上是在处理两个方面的问题:用户...

    Struts2、Spring、Freemarker自定义标签

    Spring框架也有自己的标签库,如Spring Taglib,可以简化JSP页面中的Spring Bean引用。而在Freemarker中,可以通过扩展其API创建自定义指令,实现更复杂的逻辑或功能。 总结一下,Struts2、Spring和Freemarker的...

    spring自定义切面实例

    在Spring配置文件中,可以通过`&lt;aop:aspectj-autoproxy/&gt;`标签启用AspectJ的自动代理功能。这意味着Spring容器会自动为标记了@Aspect注解的类创建AOP代理,而无需手动配置。 #### 3. **自定义注解定义切点** 为了...

Global site tag (gtag.js) - Google Analytics