一行代码搞定Spring策略模式,强的离谱

这篇具有很好参考价值的文章主要介绍了一行代码搞定Spring策略模式,强的离谱。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在Spring中大量使用策略模式来简化if/else代码,比如Spring Security 的各种AuthenticationProvider等等,但是实现方式过于麻烦,使用重复套路来实现。

一般基于Spring的策略实现

场景:关于用户订单充值(订单支付同理),我们都知道,现今的支付方式是非常的多的,例如:支付宝、微信、银联、钱包(各个APP的账户余额)等等。

查询实体Query:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ChargeQuery {
    private BigDecimal money;
    private String channel;
}

支付接口

public interface PayWayHandler {
    String handler(ChargeQuery query);
}

阿里支付功能实现

@Service
@Order(9)
public class AliPayWayHandler implements PayWayHandler {

    /**
     * 支持什么类型
     *
     * @return
     */
    @Override
    public String support() {
        return "Ali";
    }

    @Override
    public String handler(ChargeQuery query) {
        System.out.println("query = " + query);
        return "使用了" + support() + "支付了";
    }
}

微信支付实现

@Service
@Order(12)
public class WxPayWayHandler implements PayWayHandler {

    /**
     * 支持什么类型
     *
     * @return
     */
    @Override
    public String support() {
        return "Wx";
    }

    @Override
    public String handler(ChargeQuery query) {
        System.out.println("query = " + query);
        return "使用了" + support() + "支付了";
    }
}

支付调用

        Map<String, PayWayHandler> payWayHandlerMap = context.getBeansOfType(PayWayHandler.class);

        ChargeQuery chargeQuery = new ChargeQuery(new BigDecimal(100), "Ali");
        for (PayWayHandler payWayHandler : payWayHandlerMap.values()) {
        //匹配到支持的渠道类型
            if (chargeQuery.getChannel().equals(payWayHandler.support())) {
                payWayHandler.handler(chargeQuery);
                break;
            }
        }

可以看到这边通过for循环来查找实现bean,虽然相比不用策略模式使用if/else
简单多了。但是遇到其他的业务或者其他的策略模式,这边的for循环逻辑还是需要再写一遍。基于封装原则,为了减少重复代码,我为大家提供了spring-plugin
工具类,实现一行代码搞定列策略模式。下面进入正文。

spring-plugin实现策略模式

POM引入

<dependency>
    <groupId>com.admin4j.spring</groupId>
    <artifactId>spring-plugin</artifactId>
    <version>0.8.1</version>
</dependency> 

最新版查看:https://central.sonatype.com/artifact/com.admin4j.spring/spring-plugin

实现代码

//"Ali" 支付
ChargeQuery aliChargeQuery = new ChargeQuery(new BigDecimal(100), "Ali");
String handler = ProviderManager.load(PayWayHandler.class, aliChargeQuery.getChannel()).handler(aliChargeQuery);

最终使用String handler = ProviderManager.load(PayWayHandler.class, aliChargeQuery.getChannel()).handler(aliChargeQuery);
一行代码搞定了策略模式,减少了重复代码块。

实现原理

实现原理也是相当的简单,看一遍就懂了

public class ProviderManager {

    private ProviderManager() {
    }

    /**
     * Spring 的 IOC 容器,默认为空。
     * 默认使用了 SpringUtils(admin4j-common-spring包里) 来获取ApplicationContext。如果不想多引入`admin4j-common-spring`包的话,可将他排除
     */
    public static ApplicationContext APPLICATION_CONTEXT;
    
    private static final Map<Class<Provider<?>>, Collection<Provider<?>>> CACHED_PROVIDERS = new ConcurrentHashMap<>();

    /**
     * 加载  Provider
     *
     * @param providerClass 给定的Class
     * @param support       支持的策略
     * @return 最终的支持策略的 Provider
     */
    public static <T extends Provider<?>> T load(Class<T> providerClass, String support) {

        Collection<T> providers = loadProvider(providerClass);
        for (Provider<?> provider : providers) {

            if (Objects.equals(provider.support(), support)) {
                return (T) provider;
            }
        }

        return null;
    }

    /**
     * 返回所有的  Provider
     *
     * @param providerClass 给定的Class
     * @return 所有的 Provider
     */
    public static <T extends Provider<?>> Collection<T> all(Class<T> providerClass) {

        return loadProvider(providerClass);
    }

    /**
     * 通过class获取所有的 beans
     */
    private static <T extends Provider<?>> Collection<T> loadProvider(Class<T> providerClass) {

        return (Collection<T>) CACHED_PROVIDERS.computeIfAbsent((Class<Provider<?>>) providerClass, key -> {

            if (APPLICATION_CONTEXT == null) {
                APPLICATION_CONTEXT = SpringUtils.getApplicationContext();
            }
            Map<String, T> beansOfType = APPLICATION_CONTEXT.getBeansOfType(providerClass);
            Collection<T> values = beansOfType.values();
            ArrayList<T> ts = new ArrayList<>(values);
            AnnotationAwareOrderComparator.sort(ts);
            return (Collection<Provider<?>>) ts;
        });
    }
}

源码地址

https://github.com/admin4j/spring-plugin文章来源地址https://www.toymoban.com/news/detail-728112.html

到了这里,关于一行代码搞定Spring策略模式,强的离谱的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Hutool:一行代码搞定数据脱敏

    数据脱敏百度百科中是这样定义的: 数据脱敏,指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护。这样就可以在开发、测试和其它非生产环境以及外包环境中安全地使用脱敏后的真实数据集。在涉及客户安全数据或者一些商业性敏感数据的情况

    2024年02月13日
    浏览(57)
  • 一行代码搞定 font-size 响应式

    公司要做大屏,但是大屏还要有个嵌在系统的版本,屏幕(iframe)小了但字体大了怎么办。网上找了很多代码都很长,个人参考了资料后实现了一个一行代码 font-size 响应式。 在 html 标签中定义是为了定义全局字体基准大小,目前开发几乎所有的字体都用 rem 作为单位,而

    2024年02月03日
    浏览(48)
  • 使用策略模式实现 Spring 分布式和单机限流

    我们可以使用策略模式来统一单机限流和分布式限流的实现,提高代码的可扩展性和可维护性。 思路是定义一个 RateLimitStrategy 接口,并分别实现单机限流策略 LocalRateLimitStrategy 和分布式限流策略 DistributedRateLimitStrategy 。在 AOP 切面中,根据配置决定使用哪种限流策略。 定义策略

    2024年04月24日
    浏览(40)
  • 策略模式+Spring配置类优化多if..else思路

    场景: 假设设备上报不同类型的消息,我们要对不同类型的消息做不同的处理。如果我们通过if..else的方式处理的话会显得比较冗余。 例如: 那么对于不同消息的不同的处理逻辑我们可以单独放在一个实现类中,这些类有着相同的行为,所以我们可以定义一个接口: 针对于不

    2024年02月15日
    浏览(42)
  • 第01篇:系统化学习, 搞定Spring容器管理

    公众号 : 西魏陶渊明 CSDN : https://springlearn.blog.csdn.net 天下代码一大抄, 抄来抄去有提高, 看你会抄不会抄! Spring 是 java 开发者,永远绕不开的结。 Spring 是非常值得开发者来学习的, 以目前 Spring 在 java 领域的统治性地位, 可以说学 java 就是在学 Spring 。但是作为新入门的开发人

    2023年04月15日
    浏览(82)
  • Spring IOC 与 AOP 基础原理,一篇搞定

    控制反转,一切对象交给Spring来创建于管理,将创建与使用对象的代码进行分离作用。实现代码的解耦。 因为以前的对象创建都是在程序的创建,管理。这是所谓的正转,如今的对象的创建是在IOC中,在 IOC Container中获取。这就是反转。 DI,denpendecy inject。依赖注入,在应用

    2024年01月21日
    浏览(37)
  • 【Spring MVC】获取 @RequsetBody 标识的对象,使用适配器模式增加代码可读性

    一个技术需求引发的思考和实践: 思考 用 AOP 把校验代码 实践 用 Spring MVC 的 RequestBodyAdvice 做AOP逻辑 继承 RequestBodyAdviceAdapter 实现自己的 适配器 用自己的适配器让代码可读性增加 熟悉 Spring MVC 、Java 反射的一些实践 本文内容 澄清一个AOP校验JSON内容的思路 复习适配器模式

    2024年02月10日
    浏览(41)
  • Spring之AOP(带你一篇文章搞定AOP)

    Spring的核心之一:AOP 用的依赖(包括上篇文章讲诉的IOC依赖): AOP:面向切面编程。利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。通俗来说就是在不修改代码的情况下添加新的功能

    2024年02月16日
    浏览(52)
  • 轻松搞定Spring集成缓存,让你的应用程序飞起来!

    主页传送门:📀 传送   Spring 提供了对缓存的支持,允许你将数据存储在缓存中以提高应用程序的性能。Spring 缓存抽象基于 Java Caching API,但提供了更简单的编程模型和更高级的功能。   Spring 集成缓存提供了一种方便的方式来使用缓存,从而提高应用程序的性能。Spr

    2024年02月07日
    浏览(60)
  • Spring Boot进阶(58):轻松搞定数据存储!Spring Boot与PostgreSQL完美集成,让你的应用更稳定更高效!

            PostgreSQL是一种广泛使用的开源关系型数据库,具有可靠性高、性能优异、拥有丰富的数据类型和扩展等优点,越来越多的企业和开发者开始使用它来存储和管理数据。而Spring Boot是一种快速开发的框架,可以简化开发过程并提高开发效率。本文将介绍如何使用Sp

    2024年02月10日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包