基于SpringBoot实现调用远程服务

xiaoxiao2021-02-28  51

基于SpringBoot实现的远程服务调用

写在前面的知识概要

SpringBoot 的 @Import 用于将指定的类实例注入到Spring IOC Container中。 SpringBoot 提供了 三种使用 @Import 将 类实例注入至 Spring IOC Container中方法。

直接注入实现 ImportBeanDefinitionRegistrar 接口注入实现 ImportSelector 注入 详见原文:SpringBoot构建微服务实战 之 @Import

我这里是通过实现 ImportBeanDefinitionRegistrar 接口注入的

要达到的效果

服务端:

@RemoteService(UserService.class) public class UserServiceImpl implements UserService { //实现UserService接口中的方法 }

客户端:

//在使用类中自动注入 @RemoteClient("${remote.url}") private UserService userService;

2.实现过程

自定义扫描路径

ImportBeanDefinitionRegistrar接口方法: void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) ResourceLoaderAware 接口方法: void setResourceLoader(ResourceLoader resourceLoader)

话不多说,上代码

public class RemoteServiceScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware { private ResourceLoader resourceLoader; @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(RemoteServiceScan.class.getName())); ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry); if (resourceLoader != null) { scanner.setResourceLoader(resourceLoader); } scanner.addIncludeFilter(new AnnotationTypeFilter(RemoteService.class)); scanner.doScan(annoAttrs.getStringArray("value")); } @Override public void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } //增加扫描机制 private static class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner { public ClassPathMapperScanner(BeanDefinitionRegistry registry) { super(registry); } @Override protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages); if (beanDefinitions.isEmpty()) { logger.warn("No Remote Service was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration."); } else { processBeanDefinitions(beanDefinitions); } return beanDefinitions; } private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) { for (BeanDefinitionHolder holder : beanDefinitions) { try { MetadataReader mr = this.getMetadataReaderFactory().getMetadataReader(holder.getBeanDefinition().getBeanClassName()); AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(mr.getAnnotationMetadata().getAnnotationAttributes(RemoteService.class.getName())); if(null == annoAttrs) { continue; } Class<?> serviceInterface = annoAttrs.getClass("value"); if (serviceInterface == null) { serviceInterface = annoAttrs.getClass("serviceInterface"); } String name = annoAttrs.getString("name"); if (StringUtils.isEmpty(name)) { name = serviceInterface.getSimpleName(); } String path = annoAttrs.getString("path"); if (!StringUtils.isEmpty(path)) { name = path + "/" + name; } if (!name.startsWith("/")) { name = "/" + name; } GenericBeanDefinition definition = new GenericBeanDefinition(); definition.getPropertyValues().add("service", new RuntimeBeanReference(holder.getBeanName())); definition.getPropertyValues().add("serviceInterface", serviceInterface); definition.setInitMethodName("afterPropertiesSet"); RemoteType type = annoAttrs.getEnum("type"); if (RemoteType.HTTP == type) { definition.setBeanClass(EyasHttpInvokerServiceExporter.class); } else if (RemoteType.HESSIAN == type) { definition.setBeanClass(HessianServiceExporter.class); } else if (RemoteType.RMI == type) { definition.setBeanClass(RmiServiceExporter.class); } registerBeanDefinition(new BeanDefinitionHolder(definition, name), this.getRegistry()); } catch (IOException e) { e.printStackTrace(); throw new BeanDefinitionStoreException( "Failed to read candidate component class: " + holder.getBeanDefinition().getBeanClassName(), e); } } } } }

未完,待续。。。

转载请注明原文地址: https://www.6miu.com/read-2626607.html

最新回复(0)