在spring加入自己的annotation实现RPC service层

接上个贴。继续谈谈自己的annotation是如何处理的。

 

主要目的,加入一个RPC层,RPC层主要是提供透明的rpc调用的服务层和协议解析层。

 

对于service层来说,关心的是业务逻辑,用spring的aop的原理,service层提供

服务。不负责具体的rpc的协议的处理和转换,这个转换通过专门的协议的拦截器注入

从而提供各样的rpc调用,比如json-rpc,xml-rpc,edi-rpc,webservice-rpc等

 

在提供服务的service里,通过自己定义的annotation来published可以提供的rpc的

服务。

 

先定义了一个Enum来作为Annotation里的可选值,Required,作为Annontation的

一个属性,表明,这个service和method是否要作为rpc的service

 

public enum Required

{

    YES(true),NO(false);

 

    private final boolean value;

    Required(boolean value) { this.value = value; }

    public boolean value() { return value; }

}

 

定义两个值,YES,NO,yes表明需要。No表明不需要

 

接着定义自己的annotation

 

@Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD ,ElementType.PARAMETER

})

@Retention(RetentionPolicy.RUNTIME)

@Inherited

@Documented

public @interface RPC

{

    Required required() default Required.NO;

 

    String name() default  "";

}

 

这里定义的比较简单,提供了name属性和required属性,上面的ElementType.FIELD ,ElementType.PARAMETER可以去掉,annotation类似于在class上做的一个记号,标志在class上,这里有关annontation的开发将在其他的文章里单独描述

 

下面我们来写这个annontation的处理类,这里我使用的是spring的beanProcesser来进行annontation的解析。在spring的

runtime的时候,通过对所有的class的扫描,来归纳做了RPC的annotation的类。

这里需要在spring的配置文件里加入

 

<bean class="com.synchrophy.framework.test.annotation.RPCAnnotationBeanProcessor"/>

<context:component-scan base-package="com. synchrophy" />

 

这样spring就会自动的掉到RPCAnnotationBeanProcessor来进行处理

 

public class RPCAnnotationBeanProcessor implements BeanPostProcessor,PriorityOrdered

{

public Object postProcessBeforeInitialization(Object bean, String beanName)

   throws BeansException

    {

System.out.println(beanName + "(Before) : " + bean);

Class clazz = bean.getClass();

RPC rpc = (RPC)clazz.getAnnotation(RPC.class);

if(rpc!=null)

{

   boolean required = rpc.required().value();

   

   RPCServiceDescription desciption = new RPCServiceDescription();

   

   try

   {

clazz = Class.forName(clazz.getName());

   }

   catch (Exception e) {

throw new IllegalArgumentException(e);

   }

   

   String servicename;

   

   if(StringUtils.isBlank(rpc.name()))

   {

servicename = beanName;

   }

   else

   {

servicename = rpc.name();

   }

   

   desciption.setServicename(servicename);

   desciption.setClazz(clazz);

   

   Method[] ms = clazz.getMethods();

   

   for(Method m : ms)

   {

if(!Modifier.isPublic(m.getModifiers()))

   continue;

rpc = (RPC)m.getAnnotation(RPC.class);

if( (required && (rpc==null||rpc.required()==Required.YES)) 

|| (required==false && rpc!=null && rpc.required()==Required.YES))

{

   RPCServiceAPIDescription apiDesc = new RPCServiceAPIDescription();

   apiDesc.setMethod(m);    

   apiDesc.setMethodname((rpc==null||StringUtils.isBlank(rpc.name()))?m.getName():rpc.name());

   

   Class[] pts = m.getParameterTypes();

   int ind = 0;

   for(Class pt : pts)

   {

apiDesc.addParameters(ind+"", pt);

ind ++;

   }

   desciption.addApis(apiDesc);

}

   }

   

   System.out.println("=========== Annotation " + desciption);

}

return bean;

    }

 

    public int getOrder()

    {

// TODO Auto-generated method stub

return Ordered.LOWEST_PRECEDENCE - 2;

    }

}

结合上上一篇文章谈到的bean generation的流程,这里我们将这个RPCAnnotationBeanProcessor,

从BeanPostProcessor里扩展,当Application的BeanFactory进行处理的时候,会callback这里接口里定义的两个方法。

 

这里我是将annotation的处理放到before的方法里,而不是放到after里,这个也是基于bean generation的过程而决定的

当然这里也可以放到after,可以把ProrityOrder设置的High一些。

 

现在我们可以写一个测试的service了

 

接口

public interface BeanProcesserTestService

{

    public void test1();

 

    public void test2(String name);

}

 

实现

@Service("beanProcesserTestService")

@RPC()

public class BeanProcesserTestServiceImpl implements BeanProcesserTestService

{

 

    /* (non-Javadoc)

     * @see com.sunvalley.framework.test.BeanProcesserTestService#test1()

     */

    @RPC(required=Required.YES)

    public void test1()

    {

// TODO Auto-generated method stub

System.out.println("test1 ......... ");

    }

 

    /* (non-Javadoc)

     * @see com.sunvalley.framework.test.BeanProcesserTestService#test2(java.lang.String)

     */

    @RPC(required=Required.YES, name="test2")

    public void test2(String name)

    {

// TODO Auto-generated method stub

System.out.println("test2 ........ ");

    }

 

}

测试

public class TestBeanProcessor extends BaseTestCase

{

 

    /* (non-Javadoc)

     * @see junit.framework.TestCase#setUp()

     */

    protected void setUp()

    {

super.setUp();

    }

 

    public void testRPCAnnotation()

    {

BeanProcesserTestService s = (BeanProcesserTestService)this.context.getBean("beanProcesserTestService");

System.out.println(s);

    }

}

当load到context时,就可以自动的把我的BeanProcesserTestService的RPC service已经收集到了,

其中test1和test2都已经注册到, RPCService里去了。这样通过协议层的转换从而实现各种协议
的RPC调用了。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

inthirties

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值