在我们进行Spring 框架开发中,估计用到最多的就是bean 标签吧,其实在Spring中像<mvc/><context/>这类标签以及在dubbo配置的标签都是属于自定义的标签,标签的解析,已经由作者就行了解析,我们用就好了,那么我们今天就进行开发一个自己的标签,模拟 <mvc:annotation-driven/>

大家都知道

<mvc:annotation-driven/> 这个标签就是将RequestHandlerMapping  Adapter .等类进行了加载注册到了spring 容器中,

为了让大家更好的理解,我们看dubbo jar  spring webmvc jar 包下的META-INF 目录:

对就是这三个文件,需要我们进行配置: 

1.xsd :xml 约束文件,懂XML的就知道,用来约束我们XML 标签规范的,属性等
2.spring.handlers. :用来解析我们XML的处理器,后面我会给大家说,你一定懂
3.spring.schemas :里面是用来标示xsd 的地址的;

我们看dubbo的spring.handlers 文件:忽略前面的地址,主要是后面的class路径,会被Spring反射调用的

http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler

为什么说,它会被反射调用呢?咋们稳扎稳打,我们看Spring源码--在BeanDefinitionParserDelegate 类中,如果不知道,请看一下我的一篇文章-:

link https://www.cnblogs.com/iscys/p/9756458.html

(1),解析自定义的标签元素,也就是说,自定义的标签都会就进入这个方法:

1.

(2),namespaceUrl  就是这个地址,比如解析到你使用了mvc dubbo 标签了,Spring就会找到这个地址,

(3),通过这个地址,我们其实可以大胆的推测出,这个handler 一定是我们在sprin g.handlers中配置的类的实例化,肯定Spring进行了解析,拿到了

后面的类,是不是呢,我们可以点开handler 获得的方法:

http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler

点开方法:

1.这个handlerMappings 其实就是 spring.handlers 的一个集合;
2.BeanUtils实例化
3.调用实例化后的init方法

getHandlerMappings 的实现:

(3),我们返回第一步,再执行parse方法,就是我们自己的自定义方法;

------好了,关于Spring 自定义解析其实,Spring 就为我们做了这几件事情

1.实例化一个 自定义handler ,调用init
2.parse 方法调用

OK,我们这么想,Spring为我们的解析将init,方法,parse 方法都写死了,说明Spring 肯定给我们开发者暴露了接口,供我们实现:

1.关于handler的实现:需要

extends NamespaceHandlerSupport 实现 init() 方法;

在init()方法中需要注册我们需要解析的标签内容就像这样;

2.关于new SpringDefinitionParse() 类需要

  implements BeanDefinitionParser 实现 其parse 方法,这个是对标签的解析;在Spring中的parse 方法就是间接性的调用这个parse方法

好了,接下来我们模拟一下mvc 的实现:

1.定义自己的xsd:放入到META-INF目录中:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.example.org/ys"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/ys"
elementFormDefault="qualified"> <xsd:complexType name="registryType"> <xsd:attribute name="address" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[ The registry address. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="port" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[ The registry default port. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute> <xsd:attribute name="default" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[ Is default. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType> <xsd:element name="mvc" type="registryType">
<xsd:annotation>
<xsd:documentation><![CDATA[ The registry config ]]></xsd:documentation>
</xsd:annotation>
</xsd:element> </xsd:schema>

2.spring.handlers :

http\://www.example.org/ys=com.spring.SpringHandlerSupport

注意这个handlers的key 是

value 就是我们实现类handler,需要自己定义;

3.spring.schemas:

http\://www.example.org/ys.xsd=META-INF/ys.xsd

4.定义自己的handler

public class SpringHandlerSupport  extends NamespaceHandlerSupport {

    @Override
public void init() { registerBeanDefinitionParser("mvc", new SpringDefinitionParse()); } }

5.定义自己的解析方法,是需要我们实现的;

public class SpringDefinitionParse implements BeanDefinitionParser {

    @Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
        
        //通过element可以得到我们标签定义的内容
String address = element.getAttribute("address");
System.out.println(address);
        //通过parseContext 我们可以获取到当前的bean 工厂;我们可以通过这个工厂进行注册bean
System.out.println(parserContext.getRegistry());
//定义RootBeanDefinition ,设置benclass,这个class对象,我们随便引进来一个类,来测试Spring是不是帮我们进行注册
RootBeanDefinition beanDefinition = new RootBeanDefinition(Test009.class);
      //设置bean 名字将bean注册到bean 工厂中
      //dubbo 是通过这种方式进行注册的
      parserContext.getRegistry().registerBeanDefinition("test009", beanDefinition);     // String methodMappingName = parserContext.getReaderContext().registerWithGeneratedName(beanDefinition);
      // System.out.println(methodMappingName);
        //spring mvc 通过这种方式注册到bean 工厂中
//parserContext.registerComponent(new BeanComponentDefinition(beanDefinition, methodMappingName));
System.err.println(parserContext.getRegistry());
return beanDefinition;
}
}

6.配置就完成了:XML我们进行测试:引入我们的schema文件路径

<?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:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:ys="http://www.example.org/ys"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.example.org/ys http://www.example.org/ys.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <ys:mvc address="dd"></ys:mvc> </beans>

7.测试:

    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException {
ApplicationContext app =new ClassPathXmlApplicationContext("classpath:my.xml"); System.out.println(app.getBean("test009"));
}

8.运行结果:

dd//解析的address内容
org.springframework.beans.factory.support.DefaultListableBeanFactory@3dd3bcd: defining beans []; root of factory hierarchy//可以看到bean工厂是 DefaultListableBeanFactory org.springframework.beans.factory.support.DefaultListableBeanFactory@3dd3bcd: defining beans [test009]; root of factory hierarchy com.java.baseknowledge.sort.Test009@6fd02e5//获得的对象

spring 自定义标签的实现的更多相关文章

  1. spring基础---->spring自定义标签(一)

    Spring具有一个基于架构的扩展机制,可以使用xml文件定义和配置bean.本博客将介绍如何编写自定义XML bean的解析器,并用实例来加以说明.其实我一直相信 等你出现的时候我就知道是你. Sp ...

  2. spring自定义标签之 自我实现

     引言: 最近心情比较难以平静,周末的两天就跑出去散心了,西湖边上走走,看日落,还是不错的.回来博客上发现,在自定义标签上,最后一步实现忘记加上了.其实,人生的路程中,我们总是实现着自我的价值,让自己 ...

  3. spring自定义标签之 规范定义XSD

    引言: spring的配置文件中,一切的标签都是spring定义好的.<bean/>等等,有了定义的规范,才能让用户填写的正常可用.想写自定义标签,但首先需要了解XML Schema De ...

  4. Spring 自定义标签配置

    前景:经常使用一些依赖于Spring的组件时,发现可以通过自定义配置Spring的标签来实现插件的注入,例如数据库源的配置,Mybatis的配置等.那么这些Spring标签是如何自定义配置的?学习Sp ...

  5. Spring自定义标签

    一.原理: 1.Spring通过XML解析程序将其解析为DOM树, 2.通过NamespaceHandler指定对应的Namespace的BeanDefinitionParser将其转换成BeanDe ...

  6. 自己构建一个Spring自定义标签以及原理讲解

    平时不论是在Spring配置文件中引入其他中间件(比如dubbo),还是使用切面时,都会用到自定义标签.那么配置文件中的自定义标签是如何发挥作用的,或者说程序是如何通过你添加的自定义标签实现相应的功能 ...

  7. Spring自定义标签解析与实现

           在Spring Bean注册解析(一)和Spring Bean注册解析(二)中我们讲到,Spring在解析xml文件中的标签的时候会区分当前的标签是四种基本标签(import.alias ...

  8. spring自定义标签学习

    看到几篇很全的自定义标签,从定义到使用,写的很好. 这里我也是在那里学习的,对学习spring源码也很有帮助. 贴出来与大家共享. http://sammor.iteye.com/blog/11009 ...

  9. Spring自定义标签的实现

    首先 简单写下 spring xml解析的过程 通过一段简单的 调用spring代码开始 public static void main(String[] args) { ApplicationCon ...

随机推荐

  1. grep init 与 grep [i]nit

    看grep的知识点的时候,在XXX博客里看到一个这样的例子,一直在纠结,纠结,init与[i]nit 匹配到的东西不应该时一样的嘛,为什么一个匹配得出来,一个不行.后来在群里问了某位大哥,耐心的讲解, ...

  2. 第一章 C#入门 (Windows窗体应用程序)(一)

    我的第一个窗体应用程序(一) [案例说明]  在文本框中显示一行文字“Hello C#!”,单击[显示]按钮后在文本框中显示文字:单击[清除]按钮后清除文本框中的内容. [案例实现步骤] 1.新建项目 ...

  3. Spark程序运行常见错误解决方法以及优化

    转载自:http://bigdata.51cto.com/art/201704/536499.htm Spark程序运行常见错误解决方法以及优化 task倾斜原因比较多,网络io,cpu,mem都有可 ...

  4. DHCP Option43配置

    在配置Option 43之前,需要保证:1. AP与DHCP服务器之间路由可达,即AP可以获取到IP地址.2. AP与AC之间路由可达,保证AP获取到AC地址后,能够与AC交互信息,建立CAPWAP隧 ...

  5. Java继承(下)

    Object类 在www.oracle中找到java 中的java.lang在中找到object类中找到可以看到在java语言中的定义 如何修改object中的equals类及测试 在object中类 ...

  6. TCP/IP学习20180701-数据链路层-IP子网寻址

    IP-子网寻址IP地址是:网络号+主机号现在主机号都要求有子网号所以IP地址就变成了网络号+子网号+主机号例如一个B类地址:210.30.109.134210.30是网络号109是子网号134是主机号 ...

  7. kubernetes核心组件kube-proxy 学习总结

    一.  kube-proxy 和 service  kube-proxy是Kubernetes的核心组件,部署在每个Node节点上,它是实现Kubernetes Service的通信与负载均衡机制的重 ...

  8. Container 、Injection

    Container: Linux容器作为一类操作系统层面的虚拟化技术成果,旨在立足于单一Linux主机交付多套隔离性Linux环境.与虚拟机不同,容器系统并不需要运行特定的访客操作系统.相反,容器共享 ...

  9. 支付宝 net

  10. centos7将可执行程序做成服务

    1.systemctl 用法:systemctl [OPT] COMMAND [NAME]…启动服务:systemctl start NAME.service停止服务:systemctl stop N ...