SpringBoot 优雅实现接口的多实现类方式

1. 样板代码

1.1. 支付类型枚举

java 复制代码
package com.example.demo.enums;

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * 支付类型枚举
 *
 * @author wangbo
 */
@Getter
@AllArgsConstructor
public enum PaymentTypeEnum {
    ALIPAY("alipay", "支付宝"),
    WECHAT("wechat", "微信"),
    UNIONPAY("unionpay", "银联");

    private final String code;
    private final String name;
}

1.2. 支付服务接口

java 复制代码
package com.example.demo.service;

import com.example.demo.enums.PaymentTypeEnum;

import java.math.BigDecimal;

/**
 * 支付服务
 *
 * @author wangbo
 */
public interface PaymentService {
    /**
     * 获取支付方式
     *
     * @return PaymentTypeEnum
     */
    PaymentTypeEnum getPaymentType();

    /**
     * 处理支付
     *
     * @param amount 金额
     */
    void processPayment(BigDecimal amount);
}

1.3. 支付服务实现类

java 复制代码
package com.example.demo.service.impl;

import com.example.demo.enums.PaymentTypeEnum;
import com.example.demo.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

/**
 * 支付服务实现-支付宝支付
 *
 * @author wangbo
 */
@Slf4j
@Service
public class PaymentServiceAlipayImpl implements PaymentService {

    @Override
    public PaymentTypeEnum getPaymentType() {
        return PaymentTypeEnum.ALIPAY;
    }

    @Override
    public void processPayment(BigDecimal amount) {
        log.info("支付宝支付: " + amount);
    }
}
java 复制代码
package com.example.demo.service.impl;

import com.example.demo.enums.PaymentTypeEnum;
import com.example.demo.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

/**
 * 支付服务实现-微信支付
 *
 * @author wangbo
 */
@Slf4j
@Service
public class PaymentServiceWechatImpl implements PaymentService {
    @Override
    public PaymentTypeEnum getPaymentType() {
        return PaymentTypeEnum.WECHAT;
    }

    @Override
    public void processPayment(BigDecimal amount) {
        log.info("微信支付: " + amount);
    }
}

1.4. 支付服务策略管理器

java 复制代码
package com.example.demo.manager;

import com.example.demo.enums.PaymentTypeEnum;
import com.example.demo.service.PaymentService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 支付服务策略管理器
 *
 * @author wangbo
 */
@Component
@AllArgsConstructor
public class PaymentServiceStrategyManager {

    private final List<PaymentService> paymentServices;

    public PaymentService getPaymentService(PaymentTypeEnum paymentTypeEnum) {
        for (PaymentService paymentService : paymentServices) {
            if (paymentService.getPaymentType().equals(paymentTypeEnum)) {
                return paymentService;
            }
        }
        throw new IllegalArgumentException("不支持的支付方式: " + paymentTypeEnum.getName());
    }
}

2. 使用代码

订单处理中需要调用支付服务

2.1. 订单服务接口

java 复制代码
package com.example.demo.service;

import com.example.demo.enums.PaymentTypeEnum;

import java.math.BigDecimal;

/**
 * 订单服务
 *
 * @author wangbo
 */
public interface OrderService {
    /**
     * 处理订单
     *
     * @param paymentTypeEnum 支付方式
     * @param amount          支付金额
     */
    void processOrder(PaymentTypeEnum paymentTypeEnum, BigDecimal amount);
}

2.2. 订单服务实现类

java 复制代码
package com.example.demo.service.impl;

import com.example.demo.enums.PaymentTypeEnum;
import com.example.demo.manager.PaymentServiceStrategyManager;
import com.example.demo.service.OrderService;
import com.example.demo.service.PaymentService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

/**
 * 订单服务实现
 *
 * @author wangbo
 */
@Service
@AllArgsConstructor
public class OrderServiceImpl implements OrderService {

    private final PaymentServiceStrategyManager paymentServiceStrategyManager;

    @Override
    public void processOrder(PaymentTypeEnum paymentTypeEnum, BigDecimal amount) {
        PaymentService paymentService = paymentServiceStrategyManager.getPaymentService(paymentTypeEnum);
        paymentService.processPayment(amount);
    }
}

3. 测试代码

java 复制代码
package com.example.demo.controller;

import com.example.demo.enums.PaymentTypeEnum;
import com.example.demo.service.OrderService;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;

/**
 * @author wangbo
 * @since 2025/10/21
 */
@RestController
@AllArgsConstructor
public class OrderController {

    private final OrderService orderService;

    @GetMapping("/order")
    public String processOrder() {
        orderService.processOrder(PaymentTypeEnum.ALIPAY, BigDecimal.TEN);
        return "支付成功";
    }

    @GetMapping("/order1")
    public String processOrder1() {
        orderService.processOrder(PaymentTypeEnum.WECHAT, BigDecimal.TEN);
        return "支付成功";
    }

    @GetMapping("/order2")
    public String processOrder2() {
        orderService.processOrder(PaymentTypeEnum.UNIONPAY, BigDecimal.TEN);
        return "支付成功";
    }
}

http://localhost:8080/order

http://localhost:8080/order1

http://localhost:8080/order2

分别调用三次后,日志如下:

java 复制代码
2025-10-21T12:01:11.144+08:00  INFO 32792 --- [demo] [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2025-10-21T12:01:11.144+08:00  INFO 32792 --- [demo] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2025-10-21T12:01:11.146+08:00  INFO 32792 --- [demo] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
2025-10-21T12:01:11.170+08:00  INFO 32792 --- [demo] [nio-8080-exec-1] c.e.d.s.impl.PaymentServiceAlipayImpl    : 支付宝支付: 10
2025-10-21T12:01:21.053+08:00  INFO 32792 --- [demo] [nio-8080-exec-3] c.e.d.s.impl.PaymentServiceWechatImpl    : 微信支付: 10
2025-10-21T12:01:26.791+08:00 ERROR 32792 --- [demo] [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.IllegalArgumentException: 不支持的支付方式: 银联] with root cause

java.lang.IllegalArgumentException: 不支持的支付方式: 银联
	at com.example.demo.manager.PaymentServiceStrategyManager.getPaymentService(PaymentServiceStrategyManager.java:27) ~[main/:na]
	at com.example.demo.service.impl.OrderServiceImpl.processOrder(OrderServiceImpl.java:24) ~[main/:na]
	at com.example.demo.controller.OrderController.processOrder2(OrderController.java:35) ~[main/:na]
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:258) ~[spring-web-6.2.9.jar:6.2.9]
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:191) ~[spring-web-6.2.9.jar:6.2.9]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.2.9.jar:6.2.9]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:991) ~[spring-webmvc-6.2.9.jar:6.2.9]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:896) ~[spring-webmvc-6.2.9.jar:6.2.9]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.2.9.jar:6.2.9]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.2.9.jar:6.2.9]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.2.9.jar:6.2.9]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.2.9.jar:6.2.9]
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) ~[spring-webmvc-6.2.9.jar:6.2.9]
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564) ~[tomcat-embed-core-10.1.43.jar:6.0]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.2.9.jar:6.2.9]
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.43.jar:6.0]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.43.jar:10.1.43]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.2.9.jar:6.2.9]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.2.9.jar:6.2.9]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.2.9.jar:6.2.9]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.2.9.jar:6.2.9]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.2.9.jar:6.2.9]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.2.9.jar:6.2.9]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:116) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:398) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:903) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1769) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1189) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:658) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
	at java.base/java.lang.Thread.run(Thread.java:1583) ~[na:na]
相关推荐
花伤情犹在3 小时前
Java Stream 高级应用:优雅地扁平化(FlatMap)递归树形结构数据
java·stream·function·flatmap
yaoxin5211233 小时前
212. Java 函数式编程风格 - Java 编程风格转换:命令式 vs 函数式(以循环为例)
java·开发语言
Q_Q19632884753 小时前
python+uniapp基于微信小程序的助眠小程序
spring boot·python·小程序·django·flask·uni-app·node.js
摇滚侠3 小时前
Spring Boot 3零基础教程,WEB 开发 Thymeleaf 属性优先级 行内写法 变量选择 笔记42
java·spring boot·笔记
滑水滑成滑头3 小时前
**发散创新:多智能体系统的探索与实践**随着人工智能技术的飞速发展,多智能体系统作为当今研究的热点领域,正受到越来越多关注
java·网络·人工智能·python
摇滚侠3 小时前
Spring Boot 3零基础教程,WEB 开发 Thymeleaf 总结 热部署 常用配置 笔记44
java·spring boot·笔记
十年小站3 小时前
一、新建一个SpringBoot3项目
java·spring boot
2401_841495643 小时前
【数据结构】最长的最短路径的求解
java·数据结构·c++·python·算法·最短路径·图搜索
麦麦鸡腿堡3 小时前
Java的代码块介绍与快速入门
java·开发语言