Skip to content

首先,我们来看这两个文件中的关键代码:

  1. 在 [AbstractApplicationExecute](file:///D:/Java_projects/damai/damai-spring-cloud-framework/damai-service-initialize/src/main/java/com/damai/initialize/execute/base/AbstractApplicationExecute.java#L15-L36) 抽象类中,定义了一个抽象方法 [type()](file:///D:/Java_projects/damai/damai-spring-cloud-framework/damai-service-initialize/src/main/java/com/damai/initialize/execute/ApplicationStartEventListenerExecute.java#L45-L47):
java
public abstract String type();
  1. 在 [ApplicationStartEventListenerExecute](file:///D:/Java_projects/damai/damai-spring-cloud-framework/damai-service-initialize/src/main/java/com/damai/initialize/execute/ApplicationStartEventListenerExecute.java#L15-L47) 类中,实现了这个抽象方法:
java
@Override
public String type() {
    return APPLICATION_EVENT_LISTENER;
}

下面我来逐一回答你的问题:

1. 为什么 public abstract String type(); 特意标明 abstract?

在抽象类中声明一个方法为 abstract 有几个重要原因:

  • 强制子类实现:抽象方法要求所有非抽象子类必须提供具体实现。这样可以确保子类不会遗漏重要的方法实现。
  • 定义契约:抽象方法定义了一个契约,规定了子类应该提供什么功能,但不规定如何实现。
  • 模板方法模式:抽象类可以定义模板方法,其中调用抽象方法,而具体实现由子类提供。

如果去掉 abstract 关键字,这个方法就会变成普通方法,需要提供具体实现:

java
// 普通方法需要提供实现
public String type() {
    // 默认实现
    return "default";
}

这种情况下,子类可以选择是否覆盖这个方法,而不是强制要求实现。

2. [ApplicationStartEventListenerExecute](file:///D:/Java_projects/damai/damai-spring-cloud-framework/damai-service-initialize/src/main/java/com/damai/initialize/execute/ApplicationStartEventListenerExecute.java#L15-L47) 不仅继承了抽象类也实现了接口,这两者是什么关系?

在 [ApplicationStartEventListenerExecute](file:///D:/Java_projects/damai/damai-spring-cloud-framework/damai-service-initialize/src/main/java/com/damai/initialize/execute/ApplicationStartEventListenerExecute.java#L15-L47) 类中:

java
public class ApplicationStartEventListenerExecute 
    extends AbstractApplicationExecute 
    implements ApplicationListener<ApplicationStartedEvent>

这表示:

  1. 继承抽象类 (extends AbstractApplicationExecute):

    • 继承了父类的成员变量和方法实现
    • 必须实现父类的抽象方法 ([type()](file:///D:/Java_projects/damai/damai-spring-cloud-framework/damai-service-initialize/src/main/java/com/damai/initialize/execute/ApplicationStartEventListenerExecute.java#L45-L47))
    • 可以覆盖父类的非final方法
  2. 实现接口 (implements ApplicationListener<ApplicationStartedEvent>):

    • 必须实现接口中定义的所有方法 (如 [onApplicationEvent()](file:///D:/Java_projects/damai/damai-spring-cloud-framework/damai-service-initialize/src/main/java/com/damai/initialize/execute/ApplicationStartEventListenerExecute.java#L39-L41))
    • 接口只是定义了契约,不提供任何实现

3. 对成员属性和成员函数的复用区别

继承抽象类的复用:

  • 可以复用父类的成员变量
  • 可以复用父类的具体方法实现
  • 可以覆盖父类的方法

实现接口的复用:

  • 接口不能包含实例变量(除了常量)
  • 接口只能定义方法签名,不提供实现(Java 8之后可以有默认实现)
  • 实现类必须提供接口方法的具体实现

总的来说,继承抽象类更多是为了代码复用和扩展,而实现接口更多是为了满足契约和获得多态能力。

在这个例子中,[ApplicationStartEventListenerExecute](file:///D:/Java_projects/damai/damai-spring-cloud-framework/damai-service-initialize/src/main/java/com/damai/initialize/execute/ApplicationStartEventListenerExecute.java#L15-L47) 通过继承 [AbstractApplicationExecute](file:///D:/Java_projects/damai/damai-spring-cloud-framework/damai-service-initialize/src/main/java/com/damai/initialize/execute/base/AbstractApplicationExecute.java#L15-L36) 获得了执行初始化任务的核心逻辑,同时通过实现 [ApplicationListener](file:///D:/Java_projects/damai/damai-spring-cloud-framework/damai-service-component/src/main/java/com/damai/event/BaseSpringEventPublisher.java#L13-L51) 接口来响应Spring的事件机制。这种设计既获得了代码复用的好处,又满足了框架集成的需求。