委派模式通过持有对象引用而非继承来复用功能,需声明接口类型、构造器初始化、避免重写方法;java 8+ 可用默认方法减少样板代码;慎用动态代理,优先静态委派;spring 无@delegate注解。

委派模式不是继承,别往extends里塞
Java里想复用一个类的功能,第一反应常是继承——但委派模式的核心恰恰是“不用继承”。它靠的是持有另一个对象的引用,把请求转给它处理。继承容易导致类层次膨胀、父类修改牵连子类;而委派让行为解耦更干净,也天然支持运行时替换被委派对象。
常见错误现象:ClassCastException 或空指针,往往是因为误把委派对象声明为父类类型却没初始化,或者在构造器里调用尚未赋值的委派实例方法。
- 委派对象通常声明为接口类型(如
Processor),而非具体实现类,方便后期替换 - 构造器中必须完成委派对象的初始化,避免
NullPointerException - 不要在委派类里重写被委派对象的方法逻辑——那说明你其实该用继承,或重构职责
Delegation 在 Java 8+ 里怎么避开手动转发
手动写一堆 delegate.doX() 很枯燥,也容易漏掉新方法。Java 8 引入的默认方法 + 接口组合,能大幅减少样板代码;Java 14+ 的记录类(record)配合密封接口(sealed)还能进一步约束委派结构。
使用场景:当你有一组稳定接口(如 Logger、Validator),但底层实现可能随环境切换(测试用 Mock,生产用 Log4j),委派就比抽象工厂更轻量。
立即学习“Java免费学习笔记(深入)”;
- 优先定义清晰接口,把委派逻辑收拢在实现类里,而不是在每个使用处重复 new
- 避免在接口里塞太多默认方法——它们会污染 API 表面,也掩盖真实依赖
- 如果委派链超过两层(A → B → C),立刻检查是否职责过载;委派不是套娃工具
和 java.lang.reflect.Proxy 混用时的坑
动态代理常被当成“自动委派”的捷径,但它只适用于接口,且所有方法调用都走反射,性能开销不可忽视。真实项目里,90% 的委派需求不需要动态代理。
常见错误现象:IllegalArgumentException: object is not an instance of declaring class,多因代理目标类型不匹配或静态方法被误代理;还有人试图用 Proxy 委派 final 类,直接抛 IllegalArgumentException。
- 静态委派(字段引用 + 显式调用)性能稳定、调试直观,应为默认选择
- 只有当需要统一拦截(如日志、权限)且目标类实现固定接口时,才考虑
Proxy -
Proxy.newProxyInstance()的类加载器参数必须和接口类一致,否则运行时报NoClassDefFoundError
Spring 的 @Delegate 不是标准 Java 特性
有人搜 “Spring Delegate 注解”,结果发现 Spring 官方根本没有 @Delegate。这是个典型混淆点:Spring Boot 3.2+ 的 @AutoConfiguration 支持条件化委派配置,但那是框架层抽象,和语言级委派模式无关。真正要用委派,还是得自己写字段 + 调用。
性能影响:Spring 管理的委派对象如果 scope 是 prototype,每次获取都是新实例,要注意状态泄漏;若用 singleton,则需确保被委派对象本身线程安全。
- 别依赖 IDE 自动补全误导——输入
@Dele可能弹出第三方库注解,非 Spring 原生 - Spring AOP 的
@Around看似像委派,实则是代理增强,执行路径完全不同 - 测试时最容易忽略委派对象的 mock 替换,导致集成测试跑成端到端










