惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
爱范儿
爱范儿
H
Help Net Security
V
Visual Studio Blog
J
Java Code Geeks
Stack Overflow Blog
Stack Overflow Blog
Microsoft Security Blog
Microsoft Security Blog
Apple Machine Learning Research
Apple Machine Learning Research
MyScale Blog
MyScale Blog
The Cloudflare Blog
Martin Fowler
Martin Fowler
D
Docker
腾讯CDC
F
Fortinet All Blogs
雷峰网
雷峰网
GbyAI
GbyAI
G
Google Developers Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Recent Announcements
Recent Announcements
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Blog — PlanetScale
Blog — PlanetScale
Engineering at Meta
Engineering at Meta
博客园 - 聂微东
博客园 - 叶小钗

博客园 - 张占岭

keycloak~通过用户ID直接置换token keycloak~缓存对象的介绍与作用 wso2-apim-mcp2改版分析 mcp1和mcp2对比 为什么前端项目使用ts比js要多了 多个IDP的用户联合方案的分析 apisix~forward-auth外部认证 apisix~response-rewrite响应头重写 springboot~关于构造方法注入和字段注入的选择 apisix~OpenResty各阶段的介绍 keycloak~aud受众字段的作用及如何生成 wso2~关于workbuddy中mcp在wso2中的授权端点 k8s~避免调度资源碎片化 WEB安全~csrf介绍 WEB安全~DPoP的介绍 WEB安全~csp的介绍 什么是中间人攻击 WEB安全~xss的介绍 k8s~pod资源限制和JVM的XMX配置 关于对wso2和keycloak的token交换的调研 keycloak~实现OAuth 2.0 Token Exchange backstage~实体的介绍及它们的关系 backstage~openapi的接入与protobuf的对比 backstage~将java服务添加到backstage backstage~对接github和gitlab backstage~开始一个backstage应用 apisix~graphQL的支持 wso2几个核心项目介绍 docker~BuildKit的介绍 k8s~secret资源的使用
springboot~ImportBeanDefinitionRegistrar在自定义RPC框架中...
张占岭 · 2026-02-27 · via 博客园 - 张占岭

一、自定义RPC框架使用场景示例

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

入口注解设计:

@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更简单