Java框架继承强调受控扩展:通过非final抽象基类、protected模板方法与钩子机制,支持安全增强而非强行覆盖,核心是复用+增量补充。

Java 继承在框架设计中不是“强行覆盖”,而是通过预留扩展点 + 受控继承 + 模板方法 + 钩子机制,让使用者在不破坏原有结构的前提下安全增强功能。
框架类通常设计为可继承的基类
成熟框架(如 Spring Batch、MyBatis、Apache Commons)会主动提供非 final 的抽象类或模板类,例如:
-
org.springframework.batch.core.step.tasklet.Tasklet是接口,但常配合AbstractTasklet或SimpleStepExecutionSplitter这类抽象基类使用 -
org.apache.ibatis.session.Configuration虽不可直接继承,但其内部Executor、StatementHandler等组件多为 protected 可替换设计 -
org.springframework.web.servlet.mvc.AbstractController明确标注为“供子类继承扩展”
这类类具备三个关键特征:
- 不是 final,允许被 extends
- 关键流程方法设为 protected 或 abstract,留出定制入口
- 构造器支持 super() 调用,且初始化逻辑分层清晰(如先 setup,再 doXXX)
用 protected 钩子方法实现轻量增强
框架不会让你重写整个 execute(),而是拆解流程并暴露钩子。典型模式如下:
立即学习“Java免费学习笔记(深入)”;
- 定义模板方法(final):
public final void process() { before(); doWork(); after(); } - 将
before()和after()设为 protected,默认空实现 - 使用者继承后只需重写
before()添加日志、权限校验或上下文准备
这样既保证主流程不变,又避免重复编写核心逻辑。比如:
public class LoggingDataProcessor extends AbstractDataProcessor {
@Override
protected void before() {
log.info("Start processing for {}", getTaskId());
}
}构造阶段支持子类参与初始化
框架基类常提供带参构造器,并在其中调用 init() 或 onInit() 等回调:
- 子类可在构造器中传入自定义配置对象
- 或重写
protected void init(),在父类super()返回后执行专属初始化 - 避免在父类构造器中调用可能被子类重写的方法(防止 this 引用逸出)
注意访问边界与模块隔离
- 很多框架内部辅助类是 package-private(无修饰符),若你的子类不在同一包下,无法访问这些成员
- 解决方案不是硬改源码,而是:
- 查看是否提供 public/protected 的工厂方法或构建器(Builder)
- 若必须访问内部能力,优先考虑组合 + 接口适配,而非强行继承
- Maven 多模块项目中,可将自定义子类放在与框架类同名包路径下(需确认许可证允许)
新增功能优先走“添加”而非“重写”
继承扩展的本质是 复用 + 增量补充:
- 添加新字段:如扩展
HttpMessageConverter时增加private Charset fallbackCharset; - 添加新方法:如
CustomJsonConverter新增setPrettyPrint(boolean)控制格式化开关 - 重写仅限行为微调:用
super.convert()保底,再包装结果或处理异常
不推荐为加一行日志就重写整个 writeInternal() 方法体——那已偏离继承本意,属于侵入式修改。


















