当前位置: 首页 > news >正文

springboot在自定义RPC框架中的使用

入口注解设计:

@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(RpcComponentRegistrar.class) public @interface EnableRpc { // 扫描的包路径 String[] basePackages() default {}; // 注册中心类型 RegistryType registry() default RegistryType.ZOOKEEPER; // 协议类型 ProtocolType protocol() default ProtocolType.HTTP; }

2. RpcComponentRegistrar的多阶段注册

public class RpcComponentRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware { private Environment environment; @Override public void setEnvironment(Environment environment) { this.environment = environment; } @Override public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry ) { // 阶段1:解析配置 AnnotationAttributes attributes = AnnotationAttributes.fromMap( importingClassMetadata.getAnnotationAttributes(EnableRpc.class.getName())); // 阶段2:根据配置动态注册核心组件 registerRegistryCenter(registry, attributes); registerProtocolProcessor(registry, attributes); registerLoadBalancer(registry, attributes); // 阶段3:扫描并注册服务提供者和消费者 scanAndRegisterServices(registry, attributes); } private void registerRegistryCenter( BeanDefinitionRegistry registry, AnnotationAttributes attributes ) { RegistryType type = attributes.getEnum("registry"); RootBeanDefinition beanDefinition = new RootBeanDefinition(); beanDefinition.setBeanClassName(getRegistryClassByType(type)); // 从Environment读取配置(如zookeeper地址) beanDefinition.getPropertyValues().add("address", environment.getProperty("rpc.registry.address")); registry.registerBeanDefinition("rpcRegistryCenter", beanDefinition); } private void scanAndRegisterServices( BeanDefinitionRegistry registry, AnnotationAttributes attributes ) { // 1. 扫描@ServiceProvider注解的服务提供者 Set<BeanDefinition> providers = scanForAnnotations( attributes.getStringArray("basePackages"), ServiceProvider.class); // 2. 为每个服务提供者注册特殊的BeanDefinition for (BeanDefinition providerDef : providers) { GenericBeanDefinition enhancedDef = enhanceForProvider(providerDef); registry.registerBeanDefinition( providerDef.getBeanClassName(), enhancedDef); // 3. 同时自动注册到服务注册中心 registerToServiceDiscovery(providerDef); } // 4. 扫描@RpcReference注解的消费方 // 需要创建ReferenceBeanFactoryBean来处理动态代理 registerReferenceProcessor(registry, attributes); } private GenericBeanDefinition enhanceForProvider(BeanDefinition originalDef) { GenericBeanDefinition definition = new GenericBeanDefinition(originalDef); // 添加服务暴露的初始化逻辑 definition.setInitMethodName("exportService"); // 添加后置处理器来监听服务状态 definition.getPropertyValues().add("serviceRegistry", new RuntimeBeanReference("rpcRegistryCenter")); return definition; } private void registerReferenceProcessor( BeanDefinitionRegistry registry, AnnotationAttributes attributes ) { // 创建处理@RpcReference注解的后置处理器 RootBeanDefinition processorDef = new RootBeanDefinition( RpcReferenceAnnotationBeanPostProcessor.class); // 注入必要的依赖 processorDef.getPropertyValues().add("registryCenter", new RuntimeBeanReference("rpcRegistryCenter")); processorDef.getPropertyValues().add("loadBalancer", new RuntimeBeanReference("rpcLoadBalancer")); registry.registerBeanDefinition( "rpcReferenceAnnotationBeanPostProcessor", processorDef); } }

3. RPC框架的关键扩展点设计

服务消费者代理工厂:

public class RpcReferenceFactoryBean implements FactoryBean<Object> { private Class<?> interfaceType; private String serviceName; private LoadBalancer loadBalancer; @Override public Object getObject() throws Exception { // 创建动态代理,实现RPC调用 return Proxy.newProxyInstance( interfaceType.getClassLoader(), new Class<?>[] {interfaceType}, new RpcInvocationHandler(serviceName, loadBalancer) ); } @Override public Class<?> getObjectType() { return interfaceType; } }

注解处理器:

public class RpcReferenceAnnotationBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware { @Override public Object postProcessAfterInitialization(Object bean, String beanName) { // 扫描bean中所有@RpcReference注解的字段 Field[] fields = bean.getClass().getDeclaredFields(); for (Field field : fields) { if (field.isAnnotationPresent(RpcReference.class)) { RpcReference reference = field.getAnnotation(RpcReference.class); // 为每个引用创建代理并注入 Object proxy = createProxy(field.getType(), reference); field.setAccessible(true); try { field.set(bean, proxy); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } } return bean; } }

二、架构师的设计模式总结

1. 动态注册模式

模板方法流程:

1. 解析注解元数据(AnnotationMetadata) 2. 根据元数据创建或选择BeanDefinition 3. 修改BeanDefinition(替换BeanClass、添加构造参数) 4. 批量注册到Registry

2. 策略模式的应用

// 根据配置动态选择实现类 private String getRegistryClassByType(RegistryType type) { switch (type) { case ZOOKEEPER: return "com.rpc.registry.ZookeeperRegistry"; case NACOS: return "com.rpc.registry.NacosRegistry"; case ETCD: return "com.rpc.registry.EtcdRegistry"; default: throw new IllegalArgumentException(); } }

3. 装饰器模式的使用

// 增强原始BeanDefinition private GenericBeanDefinition enhanceForProvider(BeanDefinition originalDef) { GenericBeanDefinition definition = new GenericBeanDefinition(originalDef); // 装饰1:添加初始化方法 definition.setInitMethodName("exportService"); // 装饰2:添加销毁方法 definition.setDestroyMethodName("unexportService"); // 装饰3:添加服务版本属性 definition.getPropertyValues().add("version", "1.0.0"); return definition; }

三、扩展性设计

// 允许通过SPI扩展组件 private void registerExtensions(BeanDefinitionRegistry registry) { ServiceLoader<RpcExtension> loader = ServiceLoader.load(RpcExtension.class); for (RpcExtension extension : loader) { RootBeanDefinition def = new RootBeanDefinition(extension.getClass()); registry.registerBeanDefinition( extension.extensionName(), def ); } }

四、与Spring Boot AutoConfiguration的对比

特性ImportBeanDefinitionRegistrar@Configuration + @Bean
注册时机更早(在ConfigurationClassParser阶段)稍晚(BeanFactoryPostProcessor之后)
动态性可根据元数据动态决定注册哪些Bean静态声明,条件化需借助@Conditional
批量处理天然支持批量扫描和注册需要手动遍历或使用@Import多个配置
Bean定义修改可直接操作BeanDefinition只能创建新的BeanDefinition
适用场景框架集成、注解驱动、插件化简单条件装配、第三方Bean声明

选择建议

  • 当需要基于注解属性动态决定注册逻辑时,用ImportBeanDefinitionRegistrar
  • 当Bean的数量或类型在编译期无法确定时,用ImportBeanDefinitionRegistrar
  • 当只是根据条件选择性地注册几个已知Bean时,用@Configuration+@Conditional更简单
http://www.jsqmd.com/news/483506/

相关文章:

  • ROS系统中基于强化学习算法的移动机器人路径规划策略研究:应用DQN、DDPG、SAC及TD3算法
  • DS_store文件泄露漏洞全流程演示(在kali系统中报错时搭建虚拟环境演示以及其他方法)
  • AIGlasses_for_navigation数据存储方案:MySQL安装配置与轨迹管理
  • 洞察2026:宁夏GEO优化市场格局与头部服务商评测 - 2026年企业推荐榜
  • 国产MCU实时姿态与功耗监测系统设计
  • GRU时间序列回归预测模型:基于Matlab的详细注释代码实现
  • comsol岩层开挖作用下瓦斯渗透运移模型,考虑应力作用下的渗透率变化,流固耦合物理场,使用p...
  • 基于MSPM0G3507的嵌入式PID闭环控制教学平台
  • MATLAB统一潮流控制器仿真模型:基于模块化多电平MMC的UPFC在高压输电线路的应用
  • Dell笔记本车载电源适配器:20V/90W升压+1-Wire协议认证设计
  • 2026年初实力盘点:五家可靠卷帘门热门厂家深度解析 - 2026年企业推荐榜
  • 【2026年小米春招 - 3月14日 -第一题- 农田网格】(题目+思路+JavaC++Python解析+在线测试)
  • 开箱即用:万物识别镜像Gradio界面快速体验教程
  • flutter基础04-Zone
  • Phi-3-vision-128k-instruct在科研场景的应用:论文附图数据自动提取
  • 2026年北京回龙观汽车陪驾避坑指南:5家高评价机构深度解析 - 2026年企业推荐榜
  • Qwen3-14b_int4_awq实战案例:跨境电商独立站产品页SEO文案生成系统
  • 【2026年小米春招 - 3月14日 -第二题- 安排业务先后顺序】(题目+思路+JavaC++Python解析+在线测试)
  • 造相 Z-Image 开源模型效果:多物体空间关系(遮挡、投影、比例)理解能力
  • AWE2026:膳美师携新品开启全场景高端厨电新格局
  • Z-Image-GGUF参数详解:CFG/Steps/Seed调优指南,提升生成质量与稳定性
  • 订单表拆成 100 张后,那些要命的查询该怎么做?
  • AI与世人的交互:老G与小D-跨越一百八十篇的世纪对话
  • SUPIR vs 传统图像放大:AI模型如何改变我们的工作流
  • MediaPipe Holistic极速体验:CPU上流畅运行,实现低成本高精度动作捕捉
  • 小白友好:Ollama部署DeepSeek-R1完整流程图文教程
  • 文脉定序效果展示:BGE-m3对同义替换鲁棒性测试——‘人工智能’vs‘AI’效果对比
  • RexUniNLU与Mathtype公式编辑器的智能集成
  • 从雷达检测到Matlab实践:概率密度与功率谱密度的仿真解析
  • 2026年靠谱的一字型淋浴房品牌推荐:一字型淋浴房源头工厂推荐 - 品牌宣传支持者