spring通過註解自動暴露Hessian服務

Hessian與spring集成

Hessian可以與spring完美無縫的集成,我們先來看一下如何集成:

服務端服務暴露

@Autowired private HelloService helloService; @Bean(name = "/helloService") public HessianServiceExporter exportHelloService() { HessianServiceExporter exporter = new HessianServiceExporter(); exporter.setService(helloService); exporter.setServiceInterface(HelloService .class); return exporter; }

以上使用spring在代碼配置聲明bean的方式暴露了一個hession服務:
http://localhost:8080/Hello/helloService

客戶端聲明與調用

http://localhost:8080/Hello/helloService com.test.hello.service.HelloService

調用

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:/spring/ApplicationContext.xml"); HelloService helloService = (HelloService) context.getBean("helloService"); helloService.sayHi("hi, i am client");

存在的問題

上述的方法是最常用的集成方式,但存在一個問題,如果我們現在要在服務端暴露另外一個服務,那麼需要添加如下代碼:

@Autowired private AnotherService1 anotherService; @Bean(name = "/anotherService") public HessianServiceExporter exportAnotherService() { HessianServiceExporter exporter = new HessianServiceExporter(); exporter.setService(anotherService); exporter.setServiceInterface(AnotherService .class); return exporter; }

如果再來一個服務呢,那我們就再添加類似的代碼,能不能不重複添加這些類似的暴露代碼呢?

使用註解自動暴露服務

首先,新建一個叫HessianService的註解類,注意這個註解類包含了spring的Service註解

import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.stereotype.Service; @Target({ java.lang.annotation.ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Documented @Service public @interface HessianService { public abstract String value() default ""; }

接著,我們把原先用@Service註解的服務類換成@HessianService

@HessianService public class HelloServiceImpl implements HelloService { ... ... }

然後,我們使用spring的BeanFactoryPostProcessor機制,動態暴露hessian服務

@Component public class HessianServiceScanner implements BeanFactoryPostProcessor { public void postProcessBeanFactory( ConfigurableListableBeanFactory beanFactory) throws BeansException { String[] beanNames = beanFactory .getBeanNamesForAnnotation(HessianService.class); for (String beanName : beanNames) { String className = beanFactory.getBeanDefinition(beanName) .getBeanClassName(); Class> clasz = null; try { clasz = Class.forName(className); } catch (ClassNotFoundException e) { throw new BeanInitializationException(e.getMessage(), e); } String hessianServiceBeanName = "/" + beanName.replace("Impl", ""); BeanDefinitionBuilder builder = BeanDefinitionBuilder .rootBeanDefinition(HessianServiceExporter.class); builder.addPropertyReference("service", beanName); builder.addPropertyValue("serviceInterface", clasz.getInterfaces()[0].getName()); ((BeanDefinitionRegistry) beanFactory).registerBeanDefinition( hessianServiceBeanName, builder.getBeanDefinition()); } } }