服务总线学习
服务总线学习
@BusService 注解与 CGLIB 动态代理机制学习记录
1. 概述
本次学习深入探讨了 @BusService 注解配合 CGLIB 动态代理实现的无本地实现接口代理机制,了解了服务总线架构中客户端如何通过动态代理调用远程服务。
2. @BusService 注解的作用
2.1 注解定义
@BusService 注解位于 /platform/00_depends/00_sunri-bus-service-dependency-thrift/src/main/java/com/sunri/annotation/BusService.java,包含以下关键属性:
name()- 服务名称(如 "cygdevopsweb")dataclass()- 数据类别(如 "statistic")app()- 应用名称datatype()- 数据类型
2.2 注解处理流程
- 扫描:
ServiceBusBeanAutoDefinitionConfig.definitionConsumer()方法扫描带有@BusService注解的接口 - 验证:检查注解有效性、服务名称、排除列表等
- 过滤:确保接口属于指定包名且未重复注册
3. CGLIB 动态代理机制
3.1 代理对象创建位置
在 ServiceBusBeanAutoDefinitionConfig.java 第409-445行的循环中:
if (c.isInterface()) { // 409行
if (!c.getName().contains(pkgname)) { // 410-412行
continue;
}
// ... 验证逻辑 ...
// Bean构建
BusService service = (BusService) c.getAnnotation(BusService.class); // 417行
if (service == null || "".equals(service.name()) || exclude.contains(service.name())) {
continue;
}
// 创建服务信息
ServiceInfo serviceInfo = new ServiceInfo(); // 425行
serviceInfo.setPaname(StringUtils.isEmpty(service.app()) ? busClientConfig.getPaname() : service.app());
serviceInfo.setServname(service.name());
// ... 设置其他服务信息
// 注册Bean定义
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(c); // 434行
GenericBeanDefinition definition = (GenericBeanDefinition) builder.getRawBeanDefinition();
definition.getPropertyValues().add("interfaceClass", c); // 436行
definition.getPropertyValues().add("serviceInfo", serviceInfo); // 437行
definition.getPropertyValues().add("clientManager", clientManager); // 438行
definition.setBeanClass(BusClientFactoryBean.class); // 439行
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
String name = toLowerCaseFirstOne(c.getSimpleName()); // 442行
dbf.registerBeanDefinition(name, definition); // 443行
}3.2 BusClientFactoryBean 核心实现
位于 /platform/00_depends/00_sunri-bus-service-dependency-thrift/src/main/java/com/sunri/client/mapper/BusClientFactoryBean.java:
@Override
public T getObject() throws Exception {
enhancer.setSuperclass(interfaceClass); // 29行 设置要代理的接口
interceptor.setClientManager(clientManager); // 30行 设置客户端管理器
interceptor.setServiceInfo(serviceInfo); // 31行 设置服务信息
enhancer.setCallback(interceptor); // 32行 设置拦截器
return (T) enhancer.create(); // 33行 创建代理对象
}3.3 BusClientInterceptor 拦截器
位于 /platform/00_depends/00_sunri-bus-service-dependency-thrift/src/main/java/com/sunri/client/mapper/BusClientInterceptor.java:
- 拦截所有接口方法调用
- 将本地方法调用转换为远程服务调用
- 通过 Thrift 协议发送到远程服务端
4. Spring Bean 生命周期集成
4.1 Bean 定义注册
- 触发位置:
ServiceBusBeanAutoDefinitionConfig.postProcessBeanDefinitionRegistry() - 执行时机:Spring 容器启动时,在
BeanDefinitionRegistryPostProcessor阶段 - 结果:将每个带
@BusService注解的接口注册为由BusClientFactoryBean创建的 Bean
4.2 属性自动注入机制
在 ServiceBusBeanAutoDefinitionConfig.definitionConsumer() 第436-438行:
definition.getPropertyValues().add("interfaceClass", c); // 接口类
definition.getPropertyValues().add("serviceInfo", serviceInfo); // 服务信息
definition.getPropertyValues().add("clientManager", clientManager); // 客户端管理器Spring 框架内部通过反射机制自动调用对应的 setter 方法:
setInterfaceClass()→ 注入接口类setServiceInfo()→ 注入服务信息setClientManager()→ 注入客户端管理器
4.3 Bean 实例化
当应用通过 @Autowired 或 context.getBean() 获取接口实例时:
- Spring 发现该 Bean 由
BusClientFactoryBean创建 - 调用
BusClientFactoryBean.getObject() - CGLIB 创建动态代理对象
- 返回代理对象给应用
5. 工作流程总结
应用启动 → ServiceBusBeanAutoDefinitionConfig 扫描 @BusService 注解的接口
↓
为每个接口创建 BusClientFactoryBean 定义并注册到 Spring 容器
↓
应用代码获取接口实例 (@Autowired 或 getBean)
↓
Spring 调用 BusClientFactoryBean.getObject()
↓
CGLIB 创建接口的动态代理对象
↓
应用调用接口方法时由 BusClientInterceptor 拦截
↓
拦截器将方法调用转换为远程服务调用
↓
通过 Thrift 协议发送到远程服务端执行
↓
返回结果给调用方6. 关键特点
6.1 透明性
- 客户端代码无需关心底层网络通信
- 接口调用如同本地调用一样简单
6.2 解耦性
- 客户端只依赖接口定义
- 无需知道服务实现的位置和细节
6.3 动态性
- 运行时动态生成代理类
- 支持灵活的服务定位和负载均衡
7. Spring FactoryBean属性注入机制
7.1 RegisterCenterClientFactoryBean属性注入流程
调用位置:ServiceBusBeanAutoDefinitionConfig.postProcessBeanDefinitionRegistry() 第211-218行
实现机制:
- 属性值设置:通过
BeanDefinition.getPropertyValues().add()方法设置属性 - 自动注入:Spring容器在Bean创建过程中自动调用对应的setter方法
- 多态引用:
private RegisterCenterClient client字段声明为接口类型,运行时指向RegisterCenterDefaultClient实例
上下文依赖:
- 依赖Spring的Bean生命周期管理
-需要BeanDefinitionRegistryPostProcessor阶段的支持 - 依赖属性编辑器和类型转换机制
7.2完整调用链
// 1. 创建Bean定义
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(RegisterCenterClient.class);
GenericBeanDefinition definition = (GenericBeanDefinition) builder.getRawBeanDefinition();
// 2. 设置属性值(关键步骤)
definition.getPropertyValues().add("interfaceClass", RegisterCenterClient.class);
definition.getPropertyValues().add("client", zkClient); // zkClient是RegisterCenterDefaultClient实例
// 3.指定FactoryBean类
definition.setBeanClass(RegisterCenterClientFactoryBean.class);
// 4. Spring内部调用setter方法
// setInterfaceClass(RegisterCenterClient.class)
// setClient(RegisterCenterDefaultClient实例)
// 5. getObject()返回具体实现
@Override
public T getObject() throws Exception {
return (T) client; // 返回RegisterCenterDefaultClient实例
}8.技术栈
- CGLIB:用于动态代理类生成
- Spring Framework:用于 Bean 生命周期管理和依赖注入
- Thrift:用于远程服务通信协议
- Zookeeper:用于服务注册与发现
- Curator:用于Zookeeper客户端连接管理
