spring自定义标签学习,模仿dubbo实现参数配置,自定义service

主流框架都有自己的sping标签,比如dubbo

  <dubbo:application name="provider" owner="wying">
        <dubbo:parameter key="qos.enable" value="true"/>
        <dubbo:parameter key="qos.accept.foreign.ip" value="false"/>
        <dubbo:parameter key="qos.port" value="55555"/>
    </dubbo:application>

为了更深入了解spring 于是查找资料实现了自己的自定义标签

 

项目结构

首先定义xsd文件,用于校验xml格式

wys.xsd

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://www.wying.com.cn/schema/wys"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.wying.com.cn/schema/wys">



    <xsd:element name="ptConfig">
        <xsd:annotation>
            <xsd:documentation><![CDATA[ The wys config ]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:attribute name="id" type="xsd:ID">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[ The unique identifier for a bean. ]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <xsd:attribute name="name" type="xsd:string" use="required">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[ The application name. ]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <xsd:attribute name="zookeeperUrl" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[ The zookeeperUrl url. ]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>

            <xsd:attribute name="reserveV1" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[ The reserve  value1]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <xsd:attribute name="reserveV2" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[ The reserve  value2]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
        </xsd:complexType>
    </xsd:element>

    <xsd:element name="service">
        <xsd:annotation>
            <xsd:documentation><![CDATA[ The wys service ]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:attribute name="id" type="xsd:ID">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[ The unique identifier for a bean. ]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <xsd:attribute name="myRef" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[ The ref name. ]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <xsd:attribute name="myClass" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[ The class name. ]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <xsd:attribute name="reserveV1" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[ The reserve  value1]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <xsd:attribute name="reserveV2" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[ The reserve  value2]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
        </xsd:complexType>
    </xsd:element>


</xsd:schema>

 

2.编写spring.handlers  spring.schemas文件并放到项目classes META-INF目录下

spring.handlers配置自定义标签的注册类

http\://www.wying.com.cn/schema/wys=com.wying.spring.parse.WysNamespaceHandler

spring.schemas配置自定义标签xsd文件的路径

http\://www.wying.com.cn/schema/wys/wys.xsd=com/wying/spring/parse/wys.xsd

3.新建javabean存储ptConfig标签数据

PtConfigBean.java
package com.wying.spring.parse;



/**
 * description:PtConfigBean
 * date: 2020/7/24
 * author: gaom
 * version: 1.0
 */
public class PtConfigBean  {

    private  static String id;
    private  static String name;
    private  static String zookeeperUrl;
    private  static String reserveV1;
    private  static String reserveV2;



    public static String getId() {
        return id;
    }

    public static void setId(String id) {
        PtConfigBean.id = id;
    }

    public static String getName() {
        return name;
    }

    public static void setName(String name) {
        PtConfigBean.name = name;
    }

    public static String getZookeeperUrl() {
        return zookeeperUrl;
    }

    public static void setZookeeperUrl(String zookeeperUrl) {
        PtConfigBean.zookeeperUrl = zookeeperUrl;
    }

    public static String getReserveV1() {
        return reserveV1;
    }

    public static void setReserveV1(String reserveV1) {
        PtConfigBean.reserveV1 = reserveV1;
    }

    public static String getReserveV2() {
        return reserveV2;
    }

    public static void setReserveV2(String reserveV2) {
        PtConfigBean.reserveV2 = reserveV2;
    }


    public static void printPtConfig() {
       System.out.println("PtConfigBean-->id:"+id+"  name:"+ name+" zookeeperUrl:"+zookeeperUrl+" reserveV1:"+reserveV1+" reserveV2:"+reserveV2);
    }



}

解析类PtConfigBeanDefinitionParser.java用于解析ptConfig标签数据

package com.wying.spring.parse;

import com.wying.dispatcher.exception.DispatcherException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;

import java.util.concurrent.atomic.AtomicBoolean;



/**
 * description:wys:ptConfig 标签解析
 * date: 2020/7/24
 * author: gaom
 * version: 1.0
 */
public class PtConfigBeanDefinitionParser implements BeanDefinitionParser {
    //配置标签只需要加载一次
    private static AtomicBoolean isInitPtConfigBean = new AtomicBoolean(false);
    private static final Logger logger= LoggerFactory.getLogger(PtConfigBeanDefinitionParser.class);
    @Override
    public BeanDefinition parse(Element element, ParserContext parserContext){
        if(isInitPtConfigBean.get()){
            logger.error ("Duplicate definition PtConfig at <wys:PtConfig, it allows appear once only.");
            return null;
        }
        isInitPtConfigBean.set(true);
        String id=element.getAttribute("id");
        String name=element.getAttribute("name");
        String zookeeperUrl=element.getAttribute("zookeeperUrl");
        String reserveV1=element.getAttribute("reserveV1");
        String reserveV2=element.getAttribute("reserveV2");
        RootBeanDefinition def = new RootBeanDefinition();
        def.setBeanClass(PtConfigBean.class);

        PtConfigBean.setId(id);
        PtConfigBean.setName(name);
        PtConfigBean.setZookeeperUrl(zookeeperUrl);
        PtConfigBean.setReserveV1(reserveV1);
        PtConfigBean.setReserveV2(reserveV2);

        parserContext.getRegistry().registerBeanDefinition("$ptConfig",def);

        return def;
    }
}

 

 

注册标签类WysNamespaceHandler.java  注册ptConfig

package com.wying.spring.parse;

import org.springframework.beans.factory.xml.NamespaceHandlerSupport;

/**
 * description:wys   自定义spring 标签
 * date: 2020/7/24
 * author: gaom
 * version: 1.0
 */
public class WysNamespaceHandler extends NamespaceHandlerSupport {
    @Override
    public void init() {
        registerBeanDefinitionParser("ptConfig",
                new PtConfigBeanDefinitionParser());
    }
}

 

4.spring配置文件application.xml使用自定义标签

beans标签引入wys
xmlns:wys="http://www.wying.com.cn/schema/wys" 

http://www.wying.com.cn/schema/wys
http://www.wying.com.cn/schema/wys/wys.xsd
使用wys:ptConfig 设置属性
<wys:ptConfig  id='wysConfigId' name="wysConfigName" zookeeperUrl="zookeeper://localhost:2181" reserveV1="reserveV1_testmessage" reserveV2="reserveV2_testmessage"/>
<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:wys="http://www.wying.com.cn/schema/wys"
       xsi:schemaLocation="
	     http://www.springframework.org/schema/beans
	      http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
            http://www.springframework.org/schema/tx
            http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-2.5.xsd
            http://www.wying.com.cn/schema/wys
	        http://www.wying.com.cn/schema/wys/wys.xsd
           ">

    <context:annotation-config/>
    <context:component-scan base-package="com.wying"/>

    <wys:ptConfig  id='wysConfigId' name="wysConfigName" zookeeperUrl="zookeeper://localhost:2181" reserveV1="reserveV1_testmessage" reserveV2="reserveV2_testmessage"/>

    <bean id="propertyConfigurer"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="/WEB-INF/classes/property/PtConfig.properties" />
    </bean>

	 <bean id="applicationContext"
        class="org.apache.axis2.extensions.spring.receivers.ApplicationContextHolder" />
        
	<bean id="ptWebSwevice" class="com.wying.ws.PtWebSwevice" />
  


   

  <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
		<property name="url" value="${dataSource.url}" />
		<property name="username" value="${dataSource.userName}" />
		<property name="password" value="${dataSource.password}" />
		<property name="filters" value="stat" />
		<property name="maxActive" value="500" />
		<property name="initialSize" value="10" />
		<property name="maxWait" value="60000" />
		<property name="minIdle" value="10" />
		<property name="timeBetweenEvictionRunsMillis" value="60000" />
		<property name="minEvictableIdleTimeMillis" value="300000" />
		<property name="validationQuery" value="SELECT 'x'  " />
		<property name="testWhileIdle" value="true" />
		<property name="testOnBorrow" value="false" />
		<property name="testOnReturn" value="false" />
		<property name="poolPreparedStatements" value="true" />
		<property name="maxPoolPreparedStatementPerConnectionSize" value="100" />
		<property name="removeAbandoned" value="true" />
		<property name="removeAbandonedTimeout" value="1800" />
		<property name="logAbandoned" value="true" />
	</bean>




    <!-- 配置session工厂 -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource">
            <ref bean="dataSource"/>
        </property>
         <!--  <property name="mappingLocations">
			<value>classpath:/work/com/bsoft/entity/*.hbm.xml</value>
		</property>  -->
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">validate</prop>
                <prop key="hibernate.connection.autocommit">false</prop>
  				<prop key="hibernate.cache.use_query_cache">false</prop>  
                <prop key="hibernate.cache.use_second_level_cache">false</prop>  
            </props>
        </property>
       
         
    </bean>


	<!--2017/11/29  高盟  调用接口工具类  -->
	<bean id="PtUtils" class="com.wying.utils.PtUtils">
	 	
	</bean>


  
    <!-- 事物管理配置 -->
    <bean  id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory">
            <ref bean="sessionFactory"/>
        </property>
    </bean>

  <bean  id="transactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
        <property name="transactionManager" ref="transactionManager"/>
        <property name="transactionAttributes">
            <props>
          
                <prop key="add*">PROPAGATION_REQUIRED,-Exception</prop>
                <prop key="modify*">PROPAGATION_REQUIRED,+MyException</prop>
                <prop key="del*">PROPAGATION_REQUIRED</prop>
                <prop key="*">READONLY</prop>
            </props>
        </property>
   </bean> 
    
   


</beans>

 

5.启动程序测试PtConfigBean是否有xml标签配置的属性

2种方式都获取到,可以根据自己的业务使用自定义标签设置的属性了

 

 

上述使用自定义标签实现了为我们的框架定义配置信息

类似于duboo的

我们想定义自己的service了?例如dubbo服务发布配置

1.xsd文件 service节点加好,

 

2.新建 ServiceBeanDefinitionParser  自定义service解析类

package com.wying.spring.parse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;

/**
 * description:自定义service解析类
 * date: 2020/8/21
 * author: gaom
 * version: 1.0
 */
public class ServiceBeanDefinitionParser implements BeanDefinitionParser {
    private static final Logger logger= LoggerFactory.getLogger(ServiceBeanDefinitionParser.class);
    @Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        //解析<wys:service>标签
        String id = element.getAttribute("id");
        String myRef = element.getAttribute("myRef");
        String myClass = element.getAttribute("myClass");
        String reserveV1 = element.getAttribute("reserveV1");
        String reserveV2 = element.getAttribute("reserveV2");
        logger.info("BeanDefinition id:"+id+" myRef:"+myRef+" myClass:"+myClass);
        if(StringUtils.isEmpty(id)){
            logger.error("<wys:service> id must not null");
            return null;
        }

        if(StringUtils.isEmpty(myRef)&&StringUtils.isEmpty(myClass)){
            //无效配置
            logger.error("<wys:service> id:"+id+" --> myRef or myClass one must not be empty");
        }

        if(!StringUtils.isEmpty(myClass)){
            //bean对应的类
            RootBeanDefinition def = new RootBeanDefinition();
            def.setBeanClassName(myClass);
            parserContext.getRegistry().registerBeanDefinition(id, def);

        }

        if(!StringUtils.isEmpty(myRef)){
            //引用其他bean 暂未实现
           /* RootBeanDefinition def = new RootBeanDefinition();
            def.setBeanClassName("");
            parserContext.getRegistry().registerBeanDefinition(id, def);
            RuntimeBeanReference reference = new RuntimeBeanReference(id);*/
        }



        return null;
    }
}

3.WysNamespaceHandler注册解析类

package com.wying.spring.parse;

import org.springframework.beans.factory.xml.NamespaceHandlerSupport;

/**
 * description:wys   自定义spring 标签
 * date: 2020/7/24
 * author: gaom
 * version: 1.0
 */
public class WysNamespaceHandler extends NamespaceHandlerSupport {
    @Override
    public void init() {
        registerBeanDefinitionParser("ptConfig",
                new PtConfigBeanDefinitionParser());
        registerBeanDefinitionParser("service",
                new ServiceBeanDefinitionParser());
    }
}

 

4.新建测试service

WysHelloService
package com.wying.service;

import com.wying.dispatcher.exception.DispatcherException;
import com.wying.dispatcher.service.BaseService;
import org.hibernate.Session;

import java.util.Map;

/**
 * description:
 * date: 2020/8/21
 * author: gaom
 * version: 1.0
 */
public class WysHelloService implements BaseService {

    public void sayHello(){
        System.out.println("=========hello world!=========");
    }

    @Override
    public void execute(Map<String, Object> reqData, Map<String, Object> resData, Session session) throws DispatcherException {
        System.out.println("=========自定义spring bean success   =========");
    }
}

spring配置文件引用

  <wys:ptConfig  id='wysConfigId' name="wysConfigName" zookeeperUrl="zookeeper://localhost:2181" reserveV1="reserveV1_testmessage" reserveV2="reserveV2_testmessage"/>

    <wys:service  id='wysHelloService' myClass="com.wying.service.WysHelloService" myRef="" reserveV1="" reserveV2=""></wys:service>

5.启动程序

获取wysHelloService,调用sayHello方法测试成功

现在我封装的框架可以使用自己的标签配置bean使用了,不过使用spring默认的bean可以使用注解,也支持xml

我这个还没实现,必须通过xml配置bean

<wys:service  id='wysHelloService' myClass="com.wying.service.WysHelloService" myRef="" reserveV1="" reserveV2=""></wys:service>

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值