springboot~ImportBeanDefinitionRegistrar在自定义RPC框架中的使用
一、自定义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更简单
浙公网安备 33010602011771号