找回密码
 立即注册
首页 业界区 安全 springboot~ImportBeanDefinitionRegistrar在自定义RPC ...

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

恙髡 5 小时前
一、自定义RPC框架使用场景示例

1. 需求场景:服务注册与发现的自动配置

入口注解设计:
  1. @Target(ElementType.TYPE)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. @Import(RpcComponentRegistrar.class)
  5. public @interface EnableRpc {
  6.     // 扫描的包路径
  7.     String[] basePackages() default {};
  8.    
  9.     // 注册中心类型
  10.     RegistryType registry() default RegistryType.ZOOKEEPER;
  11.    
  12.     // 协议类型
  13.     ProtocolType protocol() default ProtocolType.HTTP;
  14. }
复制代码
2. RpcComponentRegistrar的多阶段注册
  1. public class RpcComponentRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {
  2.     private Environment environment;
  3.    
  4.     @Override
  5.     public void setEnvironment(Environment environment) {
  6.         this.environment = environment;
  7.     }
  8.     @Override
  9.     public void registerBeanDefinitions(
  10.         AnnotationMetadata importingClassMetadata,
  11.         BeanDefinitionRegistry registry
  12.     ) {
  13.         // 阶段1:解析配置
  14.         AnnotationAttributes attributes = AnnotationAttributes.fromMap(
  15.             importingClassMetadata.getAnnotationAttributes(EnableRpc.class.getName()));
  16.         
  17.         // 阶段2:根据配置动态注册核心组件
  18.         registerRegistryCenter(registry, attributes);
  19.         registerProtocolProcessor(registry, attributes);
  20.         registerLoadBalancer(registry, attributes);
  21.         
  22.         // 阶段3:扫描并注册服务提供者和消费者
  23.         scanAndRegisterServices(registry, attributes);
  24.     }
  25.    
  26.     private void registerRegistryCenter(
  27.         BeanDefinitionRegistry registry,
  28.         AnnotationAttributes attributes
  29.     ) {
  30.         RegistryType type = attributes.getEnum("registry");
  31.         
  32.         RootBeanDefinition beanDefinition = new RootBeanDefinition();
  33.         beanDefinition.setBeanClassName(getRegistryClassByType(type));
  34.         
  35.         // 从Environment读取配置(如zookeeper地址)
  36.         beanDefinition.getPropertyValues().add("address",
  37.             environment.getProperty("rpc.registry.address"));
  38.         
  39.         registry.registerBeanDefinition("rpcRegistryCenter", beanDefinition);
  40.     }
  41.    
  42.     private void scanAndRegisterServices(
  43.         BeanDefinitionRegistry registry,
  44.         AnnotationAttributes attributes
  45.     ) {
  46.         // 1. 扫描@ServiceProvider注解的服务提供者
  47.         Set<BeanDefinition> providers = scanForAnnotations(
  48.             attributes.getStringArray("basePackages"),
  49.             ServiceProvider.class);
  50.         
  51.         // 2. 为每个服务提供者注册特殊的BeanDefinition
  52.         for (BeanDefinition providerDef : providers) {
  53.             GenericBeanDefinition enhancedDef = enhanceForProvider(providerDef);
  54.             registry.registerBeanDefinition(
  55.                 providerDef.getBeanClassName(),
  56.                 enhancedDef);
  57.             
  58.             // 3. 同时自动注册到服务注册中心
  59.             registerToServiceDiscovery(providerDef);
  60.         }
  61.         
  62.         // 4. 扫描@RpcReference注解的消费方
  63.         // 需要创建ReferenceBeanFactoryBean来处理动态代理
  64.         registerReferenceProcessor(registry, attributes);
  65.     }
  66.    
  67.     private GenericBeanDefinition enhanceForProvider(BeanDefinition originalDef) {
  68.         GenericBeanDefinition definition = new GenericBeanDefinition(originalDef);
  69.         
  70.         // 添加服务暴露的初始化逻辑
  71.         definition.setInitMethodName("exportService");
  72.         
  73.         // 添加后置处理器来监听服务状态
  74.         definition.getPropertyValues().add("serviceRegistry",
  75.             new RuntimeBeanReference("rpcRegistryCenter"));
  76.         
  77.         return definition;
  78.     }
  79.    
  80.     private void registerReferenceProcessor(
  81.         BeanDefinitionRegistry registry,
  82.         AnnotationAttributes attributes
  83.     ) {
  84.         // 创建处理@RpcReference注解的后置处理器
  85.         RootBeanDefinition processorDef = new RootBeanDefinition(
  86.             RpcReferenceAnnotationBeanPostProcessor.class);
  87.         
  88.         // 注入必要的依赖
  89.         processorDef.getPropertyValues().add("registryCenter",
  90.             new RuntimeBeanReference("rpcRegistryCenter"));
  91.         processorDef.getPropertyValues().add("loadBalancer",
  92.             new RuntimeBeanReference("rpcLoadBalancer"));
  93.         
  94.         registry.registerBeanDefinition(
  95.             "rpcReferenceAnnotationBeanPostProcessor",
  96.             processorDef);
  97.     }
  98. }
复制代码
3. RPC框架的关键扩展点设计

服务消费者代理工厂:
  1. public class RpcReferenceFactoryBean implements FactoryBean<Object> {
  2.    
  3.     private Class<?> interfaceType;
  4.     private String serviceName;
  5.     private LoadBalancer loadBalancer;
  6.    
  7.     @Override
  8.     public Object getObject() throws Exception {
  9.         // 创建动态代理,实现RPC调用
  10.         return Proxy.newProxyInstance(
  11.             interfaceType.getClassLoader(),
  12.             new Class<?>[] {interfaceType},
  13.             new RpcInvocationHandler(serviceName, loadBalancer)
  14.         );
  15.     }
  16.    
  17.     @Override
  18.     public Class<?> getObjectType() {
  19.         return interfaceType;
  20.     }
  21. }
复制代码
注解处理器:
  1. public class RpcReferenceAnnotationBeanPostProcessor
  2.     implements BeanPostProcessor, BeanFactoryAware {
  3.    
  4.     @Override
  5.     public Object postProcessAfterInitialization(Object bean, String beanName) {
  6.         // 扫描bean中所有@RpcReference注解的字段
  7.         Field[] fields = bean.getClass().getDeclaredFields();
  8.         for (Field field : fields) {
  9.             if (field.isAnnotationPresent(RpcReference.class)) {
  10.                 RpcReference reference = field.getAnnotation(RpcReference.class);
  11.                
  12.                 // 为每个引用创建代理并注入
  13.                 Object proxy = createProxy(field.getType(), reference);
  14.                 field.setAccessible(true);
  15.                 try {
  16.                     field.set(bean, proxy);
  17.                 } catch (IllegalAccessException e) {
  18.                     throw new RuntimeException(e);
  19.                 }
  20.             }
  21.         }
  22.         return bean;
  23.     }
  24. }
复制代码
二、架构师的设计模式总结

1. 动态注册模式

模板方法流程:
  1. 1. 解析注解元数据(AnnotationMetadata)
  2. 2. 根据元数据创建或选择BeanDefinition
  3. 3. 修改BeanDefinition(替换BeanClass、添加构造参数)
  4. 4. 批量注册到Registry
复制代码
2. 策略模式的应用
  1. // 根据配置动态选择实现类
  2. private String getRegistryClassByType(RegistryType type) {
  3.     switch (type) {
  4.         case ZOOKEEPER: return "com.rpc.registry.ZookeeperRegistry";
  5.         case NACOS: return "com.rpc.registry.NacosRegistry";
  6.         case ETCD: return "com.rpc.registry.EtcdRegistry";
  7.         default: throw new IllegalArgumentException();
  8.     }
  9. }
复制代码
3. 装饰器模式的使用
  1. // 增强原始BeanDefinition
  2. private GenericBeanDefinition enhanceForProvider(BeanDefinition originalDef) {
  3.     GenericBeanDefinition definition = new GenericBeanDefinition(originalDef);
  4.    
  5.     // 装饰1:添加初始化方法
  6.     definition.setInitMethodName("exportService");
  7.    
  8.     // 装饰2:添加销毁方法
  9.     definition.setDestroyMethodName("unexportService");
  10.    
  11.     // 装饰3:添加服务版本属性
  12.     definition.getPropertyValues().add("version", "1.0.0");
  13.    
  14.     return definition;
  15. }
复制代码
三、扩展性设计
  1. // 允许通过SPI扩展组件
  2. private void registerExtensions(BeanDefinitionRegistry registry) {
  3.     ServiceLoader<RpcExtension> loader = ServiceLoader.load(RpcExtension.class);
  4.     for (RpcExtension extension : loader) {
  5.         RootBeanDefinition def = new RootBeanDefinition(extension.getClass());
  6.         registry.registerBeanDefinition(
  7.             extension.extensionName(),
  8.             def
  9.         );
  10.     }
  11. }
复制代码
四、与Spring Boot AutoConfiguration的对比

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

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

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册