Java中抽象类通过模板方法模式定义生命周期钩子:final模板方法固化init/start/stop流程,抽象方法doInit/doStart/doStop由子类实现,钩子方法initPre/startPre/stopPost供子类选择性重写,配合状态标志确保线程安全与健壮性。

在 Java 中,抽象类作为基类定义统一的生命周期钩子,核心思路是:**用模板方法模式 + 受保护的钩子方法(hook methods)**,把固定流程封装在 final 模板方法中,把可变行为延迟到子类实现。
定义标准化的生命周期阶段
先明确你关心的生命周期节点,比如:初始化前、初始化、启动前、启动中、停止前、停止后等。这些不是 Java 语言内置概念,而是业务或框架层面的约定。例如:
- initPre():资源分配前,做参数校验或上下文准备
- doInit():核心初始化逻辑(子类必须实现)
- startPre():启动前检查状态或预热
- doStart():实际启动动作(如开启线程、连接服务)
- doStop():释放核心资源(如关闭连接、中断线程)
- stopPost():清理收尾(如注销监听、记录日志)
用模板方法固化执行顺序
在抽象基类中,把流程控制权收回来,用 final 方法封装不可覆盖的骨架:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
public abstract class LifecycleComponent {
public final void init() {
initPre();
doInit();
System.out.println("✅ 初始化完成");
}
public final void start() {
if (!isInitialized()) throw new IllegalStateException("must init first");
startPre();
doStart();
System.out.println("▶️ 已启动");
}
public final void stop() {
if (!isStarted()) return;
doStop();
stopPost();
System.out.println("⏹️ 已停止");
}
// 钩子方法:默认空实现,子类按需重写
protected void initPre() {}
protected void startPre() {}
protected void stopPost() {}
// 模板方法:子类必须实现的核心行为
protected abstract void doInit();
protected abstract void doStart();
protected abstract void doStop();
// 状态跟踪(可选但推荐)
private volatile boolean initialized, started;
protected final boolean isInitialized() { return initialized; }
protected final boolean isStarted() { return started; }
protected final void markInitialized() { this.initialized = true; }
protected final void markStarted() { this.started = true; }
protected final void markStopped() { this.started = false; }
}
子类只需关注“做什么”,不操心“何时做”
子类继承后,只实现带 doXxx() 前缀的抽象方法,并选择性重写钩子方法:
立即学习“Java免费学习笔记(深入)”;
public class DatabaseService extends LifecycleComponent {
private DataSource dataSource;
@Override
protected void doInit() {
this.dataSource = createDataSource(); // 实际初始化数据源
markInitialized();
}
@Override
protected void doStart() {
// 启动连接池健康检查任务
scheduleHealthCheck();
markStarted();
}
@Override
protected void doStop() {
if (dataSource != null) {
try {
((HikariDataSource) dataSource).close();
} catch (Exception ignored) {}
}
markStopped();
}
// 在启动前打印连接信息(利用钩子)
@Override
protected void startPre() {
System.out.println("? 正在验证数据库连接...");
}
// 停止后清除静态缓存(利用钩子)
@Override
protected void stopPost() {
CacheManager.clearAll();
}
}
增强健壮性的小技巧
注意状态校验和线程安全:生命周期方法常被多线程调用(如容器自动启停),建议:
- 用 volatile 或 AtomicBoolean 管理状态标志
- 在 init()/start()/stop() 入口加简单状态判断(避免重复 init 或对已 stop 对象再 stop)
- 钩子方法本身不抛受检异常(保持模板方法简洁),必要时用运行时异常包装
- 如需异步支持,可在基类中提供 startAsync() 模板,内部委托给 CompletableFuture

















