spring使用注解暴露remoting服务

  spring提供了多种序列化方式的基于http协议的rometing服务并且在使用的接口方式,服务端使用Exporter,客户端使用FactoryBean,例如hessian的HessianExporter和HessianProxyFactoryBean。exporter有两个参数比较关键一个是serviceInterface,另外一个是service bean本身。无论是HessianExporter还是HttpInvokerExporter都需要配置这两参数,目前spring是在配置文件中进行配置:

<bean id="helloService" class="lavasoft.suths.service.HelloService"/> 
        <bean name="/hello" class="org.springframework.remoting.caucho.HessianServiceExporter">
                <property name="service" ref="helloService"/> 
                <property name="serviceInterface" value="lavasoft.suths.service.Hello"/> 
        </bean> 

很显然有时候配置总是烦人,并且容易出错,有没有更简单的方式,通过注解的方式来暴露服务。如用注解又该来如何做呢?我们知道spring先生成beandefinition,再初始化bean。这样我们先扫描带有注解的service并根据该service构造exporter的bean definition并且注册。还是看看代码吧

  for (String basePackage : basePackages) {
                Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
                for (BeanDefinition candidate : candidates) {
                    ScopeMetadata scopeMetadata = this.scopeMetadataResolver
                            .resolveScopeMetadata(candidate);
                    candidate.setScope(scopeMetadata.getScopeName());
                    String originalBeanName = this.beanNameGenerator.generateBeanName(candidate,
                            this.registry);
                    // if (candidate instanceof AbstractBeanDefinition) {
                    // postProcessBeanDefinition((AbstractBeanDefinition)
                    // candidate, originalBeanName);
                    // }
                    
                    ScannedGenericBeanDefinition bd = (ScannedGenericBeanDefinition) candidate;
                    String beanClassName = bd.getBeanClassName();
                    bd.setBeanClassName(JsonRpcExporter.class.getName());
                    bd.setBeanClass(JsonRpcExporter.class);//如果你用的hessian或者httpinvoker请换成相应的exporter
                    bd.getPropertyValues().add("service",
                            applicationContext.getBean(originalBeanName));
                    bd.getPropertyValues().add("beanClassName", beanClassName);
                    String[] interfaces = bd.getMetadata().getInterfaceNames();
                    if (interfaces == null || interfaces.length == 0)
                        continue;
                  //  HessianServiceExporter.class.getClassLoader().getResource(name)
                    Class interf = null;
   @Override
        protected void registerDefaultFilters() {

            addIncludeFilter(new AnnotationTypeFilter(JsonRpc.class));//只扫描带有JsonRpc的注解
        }

 @Component("helloService")

@JsonRpc("helloService")
public class HelloServiceImpl implements IHelloService {

 <bean id="scanner" class="com.taofang.scanner.HessianServiceScanner">

   更新

    非常感谢yangpeihai 兄的关注。起因是这样,我看到yang兄在一个帖子上说道能不能用注解暴露服务,正好这阶段我这也在做这方面的事情包括json-rpc,一看到这个帖子我就急匆匆的发了这篇blog,代码这也是从jsonrpc中摘出来的。也存在一些bug,要不是yang兄说他那边调试有问题,我现在还不知道。我发的这个版本,我把exporter的beanName和它引用的service的beanname搞混了,恰巧的是我把两个名字设成一样的,这个bug才隐藏在这里。按yang兄的要求我整了一份hessian的完整。测试类在test包中的ResourceTest。

 bd.getPropertyValues().add("service",
                            applicationContext.getBean(originalBeanName));//这里应该是exporter的service的beanname,
  BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate,
                          "/" +   beanName );//这里才是exporter的beanname,也是请求的url中的name
	   <property name="basePackage" value="com.taofang.service"></property>
	</bean

猜你喜欢

转载自xiaoz5919.iteye.com/blog/1730552