# replace-bean-demo **Repository Path**: chesterone/replace-bean-demo ## Basic Information - **Project Name**: replace-bean-demo - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-04-30 - **Last Updated**: 2026-04-30 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # @ReplaceBean - Spring Bean 替换框架 一个基于 Spring 的 Bean 替换框架,通过注解实现基于继承关系的自动 Bean 替换,无需修改注入点。 ## 🎯 核心特性 - ✅ **自动继承链识别**: 基于类继承关系自动发现替换链 - ✅ **透明替换**: 注入点完全不需要修改 - ✅ **多层级替换**: 支持 V1 -> V2 -> V3 的多层替换 - ✅ **优先级控制**: 通过 `order` 属性控制替换优先级 - ✅ **灵活配置**: 支持按名称或类型指定替换目标 - ✅ **安全验证**: 内置循环检测、冲突检测等安全检查 ## 📦 项目结构 ``` src/main/java/com/example/replacebean/ ├── annotation/ │ └── ReplaceBean.java # 核心注解 ├── processor/ │ └── ReplaceBeanProcessor.java # 核心处理器 ├── model/ │ ├── ReplaceBeanMetadata.java # 替换元数据 │ ├── ReplaceChain.java # 替换链 │ └── BeanInheritanceGraph.java # 继承关系图 ├── exception/ │ ├── ReplaceBeanException.java # 基础异常 │ ├── ReplaceBeanConflictException.java # 冲突异常 │ └── ReplaceBeanCircularException.java # 循环异常 ├── example/ │ ├── scenario1/ # 场景1: 线性替换 │ ├── scenario2/ # 场景2: 指定名称替换 │ ├── scenario3/ # 场景3: 优先级替换 │ └── scenario4/ # 场景4: 接口多实现替换 ├── consumer/ │ └── BusinessService.java # 业务服务(消费者) └── ReplaceBeanDemoApplication.java # 启动类 ``` ## 🚀 快速开始 ### 1. 运行 Demo ```bash # 编译项目 mvn clean package # 运行应用 mvn spring-boot:run ``` ### 2. 观察输出 应用启动后会执行以下验证: - ✅ 场景1: 支付服务 V1 -> V2 -> V3 的线性替换 - ✅ 场景2: 通过指定 Bean 名称替换 - ✅ 场景3: 带优先级的替换(V3 优先级高于 V2) - ✅ 场景4: 接口多实现的链式替换 ## 💡 使用示例 ### 场景1: 简单的线性替换 (V1 -> V2 -> V3) ```java // 原始实现 @Component public class PaymentServiceImpl implements PaymentService { public String pay(String orderId, double amount) { return "V1 支付"; } } // V2 替换 V1 @Component @ReplaceBean // 自动通过继承关系发现要替换 PaymentServiceImpl public class PaymentServiceImplV2 extends PaymentServiceImpl { @Override public String pay(String orderId, double amount) { return "V2 支付"; } } // V3 替换 V2 (进而替换 V1) @Component @ReplaceBean // 自动发现要替换 PaymentServiceImplV2 public class PaymentServiceImplV3 extends PaymentServiceImplV2 { @Override public String pay(String orderId, double amount) { return "V3 支付"; } } // 注入点无需修改 @Service public class OrderService { @Autowired private PaymentService paymentService; // 实际注入的是 V3! } ``` ### 场景2: 指定 Bean 名称替换 ```java // 旧实现(使用特定名称) @Component("legacyOrderService") public class LegacyOrderServiceImpl implements OrderService { } // 新实现(明确指定要替换的 Bean) @Component @ReplaceBean("legacyOrderService") public class NewOrderServiceImpl implements OrderService { } ``` ### 场景3: 带优先级的替换 ```java // V2 - 低优先级 @Component @ReplaceBean(order = 10) // 优先级较低 public class NotificationServiceImplV2 extends NotificationServiceImpl { } // V3 - 高优先级 @Component @ReplaceBean(order = 1) // 优先级较高,会覆盖 V2 public class NotificationServiceImplV3 extends NotificationServiceImpl { } // 最终生效的是 V3 ``` ### 场景4: 接口多实现替换 ```java // 内存存储 @Component public class InMemoryStorageServiceImpl implements DataStorageService { } // Redis 存储(替换内存存储) @Component @ReplaceBean public class RedisStorageServiceImpl extends InMemoryStorageServiceImpl { } // 分布式缓存(替换 Redis) @Component @ReplaceBean public class DistributedCacheStorageServiceImpl extends RedisStorageServiceImpl { } ``` ## 🔧 注解属性说明 ```java @ReplaceBean( value = "targetBeanName", // 目标 Bean 名称(可选,默认自动推断) targetClass = TargetClass.class, // 目标 Bean 类型(可选) order = 1, // 优先级(可选,数值越小越优先) strict = true // 严格模式(可选,默认true) ) ``` | 属性 | 类型 | 默认值 | 说明 | |------|------|--------|------| | `value` | String | `""` | 要替换的目标 Bean 名称,空表示自动推断 | | `targetClass` | Class | `Object.class` | 要替换的目标 Bean 类型 | | `order` | int | `Integer.MIN_VALUE` | 替换优先级,数值越小越优先 | | `strict` | boolean | `true` | 严格模式,目标不存在时是否报错 | ## ⚙️ 工作原理 1. **扫描阶段**: `ReplaceBeanProcessor` 在 Spring 容器启动时扫描所有 Bean 2. **建图阶段**: 构建 Bean 继承关系图,识别标记了 `@ReplaceBean` 的类 3. **链识别**: 从根节点出发,追踪完整的替换链 4. **验证阶段**: 检查循环依赖、冲突等异常情况 5. **执行替换**: 按优先级执行替换,合并 BeanDefinition ## ⚠️ 注意事项 ### 必须遵守的规则 1. **替换者必须是被替换者的子类** (除非使用 `value` 明确指定) 2. **不能在 Bean 实例化后替换** (必须在 BeanDefinition 阶段) 3. **避免循环替换**: A -> B -> A 会导致启动失败 ### 限制 1. **FactoryBean 需要特殊处理** (当前版本未完全支持) 2. **AOP 代理可能需要重新应用** (当前版本简化处理) 3. **原型作用域(Prototype)的替换行为可能不符合预期** ### 最佳实践 1. ✅ 优先使用继承关系自动推断,减少硬编码 2. ✅ 为替换链添加清晰的版本号或标识 3. ✅ 在测试环境中充分验证替换效果 4. ✅ 记录替换日志,便于问题排查 ## 🧪 测试验证 运行应用后,控制台会输出详细的验证结果: ``` ========== 替换验证 ========== ✓ 场景1 - 线性替换: 期望版本: V3.0.0 实际版本: V3.0.0 实际类型: PaymentServiceImplV3 结果: ✅ 通过 ✓ 场景2 - 指定名称替换: 期望服务ID: NEW-ORDER-SERVICE-V2 实际服务ID: NEW-ORDER-SERVICE-V2 实际类型: NewOrderServiceImpl 结果: ✅ 通过 ... ``` ## 📝 技术细节 ### 核心类说明 - **ReplaceBean**: 标记需要替换的 Bean - **ReplaceBeanProcessor**: 实现 `BeanDefinitionRegistryPostProcessor`,在 Bean 定义注册阶段执行替换 - **BeanInheritanceGraph**: 维护 Bean 之间的继承关系 - **ReplaceChain**: 表示一个完整的替换链 ### 执行时机 ``` Spring 容器启动流程: 1. 扫描 Bean 定义 2. 注册 BeanDefinition 3. ✨ ReplaceBeanProcessor.postProcessBeanDefinitionRegistry() ← 在这里执行替换 4. 实例化 Bean 5. 依赖注入 6. 初始化 ``` ## 🤝 贡献 欢迎提交 Issue 和 Pull Request! ## 📄 许可证 MIT License --- **作者**: ReplaceBean Framework **版本**: 1.0.0 **最后更新**: 2026-04-30