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]
相关推荐
宸津-代码粉碎机2 分钟前
Spring Boot 4.0虚拟线程实战调优技巧,最大化发挥并发优势
java·人工智能·spring boot·后端·python
MaCa .BaKa4 分钟前
47-心里健康咨询平台/心理咨询系统
java·spring boot·mysql·tomcat·maven·intellij-idea·个人开发
木子欢儿23 分钟前
Docker Hub 镜像发布指南
java·spring cloud·docker·容器·eureka
Devin~Y34 分钟前
高并发电商与AI智能客服场景下的Java面试实战:从Spring Boot到RAG与向量数据库落地
java·spring boot·redis·elasticsearch·spring cloud·kafka·rag
蜡台38 分钟前
IDEA 一些 使用配置和插件
java·ide·intellij-idea
小码哥_常38 分钟前
一个Starter搞定六种防护,Spring Boot API的超强护盾来了
后端
磊 子1 小时前
redis详解2
java·spring boot·redis
白露与泡影1 小时前
Java面试题库及答案解析(2026版)
java·开发语言·面试
程序员阿明1 小时前
spring boot3 集成jjwt(java-jwt)版本的
java·spring boot·python
bbq粉刷匠1 小时前
Java--剖析synchronized
java·开发语言