关于自定义标签,目前对他的作用的理解是,生成新的xsd文件,制定一个处理规则,在Spring启动处理bean的时候,有关标签的bean会走自己写好的一个方法。
有什么用呢,举几个可能有用的例子。
1.启动某项目时,开头要载入一连串东西。比如数据库,日志。这个时候,可以用自定义标签封装好。代码会比不封装简洁很多,同时,因为是自己设计的自定义标签,也可以对自己要改动的参数做更显眼更精确地标记。比如,数据库,就连接名,账号密码。日志,就日志等级。
2.由于自定义标签的实现,要走一个由程序员自己实现的接口,所以,有关有些想要验证正确或者初始载入中数据处理的逻辑代码,可以统一放在这个类
3.起始检查,重要的东西起始检查,比如调用数据库,或者某些核心业务,也许是到使用是才会去实例化。那也有可能一开始有问题,但是我们并不知道,上了生产就只能等报错才知道了。现在我们也可以开始就对一些,有可能出问题的代码进行试连接,和请求测试处理。在项目启动的时候就把问题扼杀在摇篮里
4.有关于xsd文件的自定义标签还能帮我们理解,如aop,tx日志等功能的实现,开拓我们的开发视线
那么实现此方法的步骤是什么呢1
1.需要扩展的组件
2.定义一个XSD文件描述组件内容
3.实现beandefinitionParser接口,用来解析xsd文件中的定义和组件定义
4.创建子类继承重写 NamespaceHandlerSupport中的init方法,把自定义标签的’标签‘注入到spring
5.编写SpringHandle 和Springschemas文件,建立,Spring解析代码,spring配置文件,xsd文件之间的关联关系
按照上述步骤先直接上代码
1.
package com.example.entity;
public class myGame {
private String id;
private String gameName;
private String gameType;
private String star;
private String gameAdd;
public String getGameAdd() {
return gameAdd;
}
public void setGameAdd(String gameAdd) {
this.gameAdd = gameAdd;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getGameName() {
return gameName;
}
public void setGameName(String gameName) {
this.gameName = gameName;
}
public String getGameType() {
return gameType;
}
public void setGameType(String gameType) {
this.gameType = gameType;
}
public String getStar() {
return star;
}
public void setStar(String star) {
this.star = star;
}
}
<?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:tag="http://zxy.easy.test/schema/test"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://zxy.easy.test/schema/test
http://zxy.easy.test/schema/test/test.xsd">
<!-- <bean id="textBean" class="com.example.entity.person" name="MynameisBeanName"/> -->
<tag:game id="testCustom" gameName="上古卷轴" gameType="active"/>
</beans>
@Test
// myTag
public void myTag() {
BeanFactory factory = new XmlBeanFactory(new ClassPathResource(
"spring-test-bean.xml"));
myGame game = (myGame) factory.getBean("testCustom");
System.out.println(game.getGameName() + "--->" + game.getGameType() + "--->"
+ game.getGameAdd());
myGame game2=new myGame();
game2.setGameName("新创对象gameName为骑马与砍杀");
System.out.println(game2.getGameName() + "--->" + game2.getGameType() + "--->"
+ game2.getGameAdd());
}
以上分别为 待扩展测试pojo类,Springxml文件,和test主体文件
2.xsd文件
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema
xmlns="http://zxy.easy.test/schema/test"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://zxy.easy.test/schema/test"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:element name="game">
<xsd:complexType>
<xsd:attribute name="id" type="xsd:ID">
</xsd:attribute>
<xsd:attribute name="gameName" type="xsd:string">
</xsd:attribute>
<xsd:attribute name="gameType" type="xsd:string">
</xsd:attribute>
<xsd:attribute name="star" type="xsd:string">
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:schema>
3.AbstractSingleBeanDefinitionParser是
beandefinitionParser的子类,其实还是重写beandefinitionParser
package com.example.serviceImpl;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.w3c.dom.Element;
import com.example.entity.myGame;
public class UserbeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
protected Class<?> getBeanClass(Element element) {
return myGame.class;
}
protected void doParse(Element element, BeanDefinitionBuilder builder) {
try {
builder.addPropertyValue("id", element.getAttribute("id"));
builder.addPropertyValue("gameName", element.getAttribute("gameName"));
builder.addPropertyValue("gameType", element.getAttribute("gameType"));
builder.addPropertyValue("star", element.getAttribute("star"));
builder.addPropertyValue("gameAdd", "ParseAdd");
}
catch (Exception e) {
e.printStackTrace();
}
}
}
4.将game该滴定仪标签注入起始启动时,bean中名字为game的会走下面申明的对象方法
package com.example.serviceImpl;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class MynameSpaceHandle extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("game", new UserbeanDefinitionParser());
}
}
5.
SpringHandle 末尾加一条(等于号后面是注入自定义标签类在项目下的路径位置)
http\://zxy.easy.test/schema/test=com.example.serviceImpl.MynameSpaceHandle
spring.schemas末尾加一条(等于号后面是编写的xsd文件的位置)
http\://zxy.easy.test/schema/test/test.xsd=org/springframework/beans/factory/xml/test.xsd
如此配置就大功告成
需要注意的是,SpringHandle 和spring.schemas在META-INF下。没有,就创建一个META-INF。spring.schemas等于号后面的路径是resources下面的相对路径比如我的
=org/springframework/beans/factory/xml/test.xsd实际上就是resources/org/springframework/beans/factory/xml/test.xsd
他的处理顺序是,在一开始去处理factory或者application的时候,回去处理一开始注入的bean。这个时候,按照自定义标签的注入,把有规定自定义标签的类抛给自定义标签处理器。处理完成后,此bean已经转为经过自定义标签处理以后的bean。然后继续别的bean的注入。而,后面,自己新new的bean 如new myGame就不会再走自定义标签解析器了。除非手动在调取paser的情况下,他基本只会在一开始载入的时候自动处理一次。