一、自定义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更简单
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |