当前位置: 首页 > article >正文

Spring Boot:如何在业务项目中覆盖基础项目的默认实现

Spring Boot:如何在业务项目中覆盖基础项目的默认实现

在 Spring Boot 项目中,我们通常会将一些通用的功能封装到基础项目(基础模块)中,而业务项目则依赖于这个基础项目。但是,实际开发过程中,业务项目可能需要自定义某些功能的实现,而不是直接使用基础项目提供的默认实现。

本文将以 ExceptionNoticeService 为例,探讨如何在业务项目中重新实现基础项目提供的接口逻辑。


一. 场景分析

假设我们在基础项目中定义了 ExceptionNoticeService 接口,并提供了一个默认实现:

public interface ExceptionNoticeService {
    void notifyException(Exception e);
}

@Service
public class DefaultExceptionNoticeService implements ExceptionNoticeService {
    @Override
    public void notifyException(Exception e) {
        System.out.println("默认异常通知: " + e.getMessage());
    }
}

业务项目依赖于这个基础项目,但现在我们希望在业务项目中 自定义异常通知逻辑,比如通过 企业微信、钉钉或者邮件 发送异常通知,而不是使用默认的 System.out.println 方式。


二. 在业务项目中重新实现 ExceptionNoticeService

方式 1:直接提供新的 Bean 实现

Spring 允许我们在 同一个接口有多个实现 的情况下,覆盖默认实现。只需在业务项目中提供一个新的 @Service 实现:

@Service
@Primary  // 让 Spring 优先使用这个 Bean
public class CustomExceptionNoticeService implements ExceptionNoticeService {
    @Override
    public void notifyException(Exception e) {
        // 这里可以调用企业微信、钉钉、邮件等通知渠道
        System.out.println("自定义异常通知: " + e.getMessage());
    }
}

关键点:

  • @Primary 注解:当 Spring 发现多个 ExceptionNoticeService 实现时,会优先使用 @Primary 标注的 Bean。
  • 新的 @Service 组件 会覆盖基础项目中的 DefaultExceptionNoticeService,确保 Spring 使用的是业务项目中的实现。

方式 2:使用 Spring 的 Bean 覆盖机制

如果不想使用 @Primary,也可以通过 @Bean 方式在业务项目中覆盖默认实现:

2.1 在业务项目的配置类中替换 Bean
@Configuration
public class ExceptionNoticeConfig {
    @Bean
    public ExceptionNoticeService exceptionNoticeService() {
        return new CustomExceptionNoticeService();
    }
}
2.2 自定义实现
public class CustomExceptionNoticeService implements ExceptionNoticeService {
    @Override
    public void notifyException(Exception e) {
        System.out.println("自定义异常通知: " + e.getMessage());
    }
}

原理解析:

  • 业务项目的 ExceptionNoticeConfig 通过 @Bean 方法定义了新的 ExceptionNoticeService 实现。
  • Spring 会使用 新的 Bean 实例,替换默认的 DefaultExceptionNoticeService

方式 3:移除基础项目的默认实现

如果业务项目总是需要自定义实现,可以在基础项目中 不提供 @Service 的默认实现,而是让业务项目必须提供自己的实现:

修改基础项目
public interface ExceptionNoticeService {
    void notifyException(Exception e);
}

去掉 DefaultExceptionNoticeService,不再提供默认实现。

业务项目中必须提供实现
@Service
public class CustomExceptionNoticeService implements ExceptionNoticeService {
    @Override
    public void notifyException(Exception e) {
        System.out.println("自定义异常通知: " + e.getMessage());
    }
}

这样,业务项目 必须 自己实现 ExceptionNoticeService,否则 Spring 在运行时会报错 No qualifying bean of type 'ExceptionNoticeService'


方式 4:使用 @ConditionalOnMissingBean

如果基础项目希望 提供默认实现,但允许业务项目自定义覆盖,可以使用 @ConditionalOnMissingBean

4.1 修改基础项目的默认实现
@Service
@ConditionalOnMissingBean(ExceptionNoticeService.class)  // 仅当容器中没有其他 ExceptionNoticeService 时才生效
public class DefaultExceptionNoticeService implements ExceptionNoticeService {
    @Override
    public void notifyException(Exception e) {
        System.out.println("默认异常通知: " + e.getMessage());
    }
}
4.2 在业务项目中提供自定义实现
@Service
public class CustomExceptionNoticeService implements ExceptionNoticeService {
    @Override
    public void notifyException(Exception e) {
        System.out.println("自定义异常通知: " + e.getMessage());
    }
}

原理解析:

  • 基础项目的 DefaultExceptionNoticeService 只有在没有其他 ExceptionNoticeService 实现时才会生效
  • 业务项目定义了 CustomExceptionNoticeService 后,Spring 容器中已经存在了 ExceptionNoticeService,基础项目的默认实现就不会被加载
  • 这样,我们既能提供默认实现,又允许业务项目自定义覆盖,更加灵活。

三. 总结

在 Spring Boot 业务项目中覆盖基础项目的 ExceptionNoticeService 实现,可以使用以下方式:

方式适用场景关键技术点
@Primary业务项目提供新实现,覆盖默认实现@Primary 让 Spring 选择业务项目的 Bean
@Bean 覆盖业务项目通过 @Configuration 配置新实现@Configuration 类中定义新的 Bean
@ConditionalOnMissingBean基础项目提供默认实现,业务项目可覆盖仅当 没有其他 Bean 时,才加载默认实现
基础项目不提供默认实现业务项目必须提供实现仅定义接口,避免无用的默认实现

如果:

  • 基础项目想提供默认实现,但业务项目可以覆盖 → 使用 @ConditionalOnMissingBean
  • 业务项目总是需要自定义实现基础项目不提供默认实现
  • 业务项目只想覆盖默认实现使用 @Primary@Bean

4. 参考资料

  • Spring Boot 官方文档
  • Spring @Primary 注解
  • Spring @ConditionalOnMissingBean
  • Spring @Bean 注解

在这里插入图片描述


http://www.kler.cn/a/585270.html

相关文章:

  • 【C++项目实战】校园公告搜索引擎:完整实现与优化指南
  • 笔记:记一次使用RabbitMq的x-delayed-message延迟消息插件,出现消息立即消费,延迟时间后再次消费,引发的重复消费问题
  • 群发邮件前的邮箱预热:构建良好发件信誉的关键步骤
  • 数据可信、隐私可控:CESS 如何打造波卡生态数据新基建?
  • VS性能分析工具
  • ollama API 本地调用
  • MTK Android12 最近历史任务 最左侧的清除历史任务改到页面底部
  • SAP IBP for Supply Chain Certification Guide (Parag Bakde, Rishabh Gupta)
  • Go语言入门基础详解
  • 深入浅出消息队列 (MQ)
  • 提升开发效率的FPGA/IC小工具
  • CSS3学习教程,从入门到精通,CSS3 选择器语法知识点及案例代码(3)
  • 区块链技术与 DICT(数字化信息与通信技术)的结合
  • 江苏无锡一家汽车零部件企业终止,拓展氢燃料电池存不确定性
  • 网易爆米花 1.8.2| 免费无广告,智能刮削,聚合6大网盘,全端无缝看片
  • ArcGIS助力水文分析:数据处理、地图制作与流域特征提取
  • uni-app打包h5并部署到nginx,路由模式history
  • QKV矩阵:优维大模型自注意力机制的数学之美
  • TCP 采用三次握手建立连接的原因
  • 30天学习Java第六天——Object类