SpringPlugin-Core在业务中的应用

Lithe-IDEA:面向Spring Boot的轻量级开源Java IDE IDE(集成开发环境)是Java开发者的核心生产力工具,其本质是基于语言服务、代码分析与项目构建能力的可扩展工作台。现代Java开发已高度聚焦于Spring Boot生态,对启动速度、内存占用和框架感知能力提出更高要求。Lithe-IDEA并非简单裁剪的‘精简版IDEA’,而是基于IntelliJ Platform内核重构的JVM专用开发工作台,通过剥离企业级功能模块、强化Spring Boot专属能力(如@ConfigurationProperties校验、Actuator端点导航)、采用按需PSI解析与 阅读详情

前言

一直负责部门的订单模块,从php转到Java也是如此,换了一种语言来实现订单相关功能。那么Spring里有很多已经搭建好基础模块的设计模式来帮助我们解耦实际业务中的逻辑,用起来非常的方便!就比如我们的订单操作模块。生成订单后,有很多操作。比如:取消、支付、关闭…等等。那么用设计模式的思想去处理这些不同的操作,最好用的就是策略模式来解决它们!把不同的操作分配到不同的实现类里去。这不,我发现了一个不错的东西Spring plugin!

Spring Plugin

Spring plugin这个小东西我也是在看一些开源项目才看到的,感觉还不错。就立马拿来用了下,把它带到我们业务场景里去。这不,带大家体验下。

下面用Spring plugin来重构下订单的相关操作实现。这里我们只模拟,支付和关闭的操作。最后再来简单分析下Spring plugin的原理

实战

首先呢、定义一个操作类型的枚举类,来边界下当前我们系统支持的操作类型!

public enum OrderOperatorType {
    /**
     * 关闭
     */
    CLOSED,

    /**
     * 支付
     */
    PAY
    ;
}

第二步、定义操作接口,实现Spring plugin的Plugin<S>接口,和配置插件

public interface OrderOperatorPlugin extends Plugin<OrderOperatorDTO> {

    /**
     * 定义操作动作
     * @param operator
     * @return
     */
    public Optional<?> apply(OrderOperatorDTO operator);
}

//配置插件,插件写好了,我们要让插件生效!
@Configuration
@EnablePluginRegistries({OrderOperatorPlugin.class})
public class OrderPluginConfig {
}

第三步 、定义具体的实现类(支付操作、关闭操作)

@Component
public class PayOperator implements OrderOperatorPlugin {

    @Override
    public Optional<?> apply(OrderOperatorDTO operator) {
        //支付操作
        //doPay()
        return Optional.of("支付成功");
    }

    @Override
    public boolean supports(OrderOperatorDTO operatorDTO) {
        return operatorDTO.getOperatorType() == OrderOperatorType.PAY;
    }
}



@Component
public class ClosedOperator implements OrderOperatorPlugin {

    @Override
    public Optional<?> apply(OrderOperatorDTO operator) {
        //关闭操作
        //doClosed()
        return Optional.of("关闭订单成功");
    }

    @Override
    public boolean supports(OrderOperatorDTO operatorDTO) {
        return operatorDTO.getOperatorType() == OrderOperatorType.CLOSED;
    }
}

这里要注意的是实现 supports方法,此方法返回的是一个boolean值,直观的看起来就是一个选择器的条件,这里可直接认为,当Support返回True的时候,就找到了当前操作的实现类!

两个不同的实现类定义好,那么我们怎么找到具体的实现类呢?

最后、定义业务接口,和业务实现类

public interface OrderService {

    /**
     * 操作订单接口
     * @param operator
     * @return
     */
    Optional<?> operationOrder(OrderOperatorDTO operator);
}


@Service
public class OrderServiceImpl implements OrderService {

    @Resource
    PluginRegistry<OrderOperatorPlugin, OrderOperatorDTO> orderOperatorPluginRegistry;

    @Override
    public Optional<?> operationOrder(OrderOperatorDTO operator) {
        OrderOperatorPlugin pluginFor = orderOperatorPluginRegistry.getPluginFor(operator);
        return pluginFor.apply(operator);
    }
}

在业务接口实现类里我们注入了

@Resource
PluginRegistry<OrderOperatorPlugin, OrderOperatorDTO> orderOperatorPluginRegistry;

名字一定是 接口名 + Registry,我这里是orderOperatorPluginRegistry至于为什么要这样写,等回我们分析源码的时候看一下。目前这样写就对了。

接下来我们测试下

@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderOperatorPluginTest {

    @Resource
    OrderService orderService;

    @Resource
    ApplicationContext applicationContext;

    @Test
    public void test_operation_closed() {
        final OrderOperatorDTO operator = new OrderOperatorDTO();
        operator.setOperatorType(OrderOperatorType.CLOSED);
        Optional<?> optionalO = orderService.operationOrder(operator);

        Assertions.assertEquals("关闭订单成功", optionalO.get());
    }


    @Test
    public void test_operation_pay() {
        final OrderOperatorDTO operator = new OrderOperatorDTO();
        operator.setOperatorType(OrderOperatorType.PAY);
        Optional<?> optionalO = orderService.operationOrder(operator);

        Assertions.assertEquals("支付成功", optionalO.get());
    }
}

这个运行结果是没有问题的,可以自己把代码下载下来,跑一下~~🤪🤪

感受

如果我把整个订单的流程都当作不同的插件来开发的话…创建订单是一个流程、在这个流程的过程中,我们分别在不同的位置插入不同的插件。比如下图!


最后,这只把所以Plugin组织起来,是不是就可以搞定一套完整的订单流程了,而我们做的只是面对插件开发,把注意力集中到某个插件中就可以了呢?或许下次订单重构的时候,我可以会这样的去尝试下!

源码重点分析

首先看下注册插件的注释EnablePluginRegistries

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Import({PluginRegistriesBeanDefinitionRegistrar.class})
public @interface EnablePluginRegistries {
    Class<? extends Plugin<?>>[] value();
}

value属性是一个数组,必须实现Plugin接口,这个是定义插件的基本条件~。

再看Import注释,PluginRegistriesBeanDefinitionRegistrar实现了ImportBeanDefinitionRegistrar接口,这个有点味道了,

public class PluginRegistriesBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
  
}

之前我有一个文章是分析相关加载类到容器的一篇文章,请看下面文章的介绍。

ImportBeanDefinitionRegistrar的作用

直接看核心代码

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
  			//当前我只注册了一个 插件 OrderOperatorPlugin
        Class<?>[] types = (Class[])((Class[])importingClassMetadata.getAnnotationAttributes(EnablePluginRegistries.class.getName()).get("value"));
        Class[] var4 = types;
        int var5 = types.length;
				//长度也就为1
        for(int var6 = 0; var6 < var5; ++var6) {
            Class<?> type = var4[var6];
          	//是FactoryBean 见名思义。PluginRegistryFactoryBean#getObject 的方法最终返回的是 OrderAwarePluginRegistry 看名字是支持排序的功能。
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(PluginRegistryFactoryBean.class);
            builder.addPropertyValue("type", type);
            AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
            Qualifier annotation = (Qualifier)type.getAnnotation(Qualifier.class);
            if (annotation != null) {
                AutowireCandidateQualifier qualifierMetadata = new AutowireCandidateQualifier(Qualifier.class);
                qualifierMetadata.setAttribute(AutowireCandidateQualifier.VALUE_KEY, annotation.value());
                beanDefinition.addQualifier(qualifierMetadata);
            }
						
          	//插件上没有添加 Qualifier 所以为null, nulll的话就给拼接上 Registry! 这就是为啥注入的时候用 插件名 + Registry、另外 PluginRegistryFactoryBean实现了PluginRegistry。
            String beanName = annotation == null ? StringUtils.uncapitalize(type.getSimpleName() + "Registry") : annotation.value();
            registry.registerBeanDefinition(beanName, builder.getBeanDefinition());
        }

    }

那么注入容器后,调用getPluginFor找到当前策略的实现类。

// OrderAwarePluginRegistry 类
public T getPluginFor(S delimiter) {
  Iterator var2 = super.getPlugins().iterator();

  Plugin plugin;
  do {
    if (!var2.hasNext()) {
      return null;
    }

    plugin = (Plugin)var2.next();
    //这里判断 supports的方法 返回true时即跳出Loop
  } while(plugin == null || !plugin.supports(delimiter));

  return plugin;
}


//另外 super.getPlugins里 会调用 initializa的方法,即插件是支持排序功能的,只要在插件上加入Order()注释即可。
protected List<T> initialize(List<T> plugins) {
  List<T> result = super.initialize(plugins);
  Collections.sort(result, this.comparator);
  return result;
}

代码在GitHub

spring-plugin 插件化开发 Spring Plugin 是一个允许你为 Spring 应用程序定义插件接口并在运行时动态加载插件实现的库。supports 方法是 Plugin 接口提供的,用于寻找执行类。定义 PayServicePlugin 继承 Plugin 接口。实现 PayServicePlugin 接口​​​​​​​。可以看到传入不同的 name 就可以动态切换支付方式。PayContext 上下文​​​​​​​。 阅读详情

相关推荐

spring-plugin-core-1.2.0.RELEASE.jar

spring-plugin-core-1.2.0.RELEASE

Spring之Core模块

Core模块主要的功能是实现了控制反转与依赖注入、Bean配置以及加载。Core模块中有Beans、BeanFactory、BeanDefinitions、ApplicationContext等概念 BeanFactory BeanFactory是实例化、配置、管理众多bean的容器 在Web程序中用户不需要实例化Beanfactory,Web程序加载的时候会自动实例化B...

weixin_30909575的博客 365

spring-plugin-core-2.0.0.RELEASE-API文档-中文版.zip

赠送jar包:spring-plugin-core-2.0.0.RELEASE.jar; 赠送原API文档:spring-plugin-core-2.0.0.RELEASE-javadoc.jar; 赠送源代码:spring-plugin-core-2.0.0.RELEASE-sources.jar; 赠送Maven依赖信息文件:spring-plugin-core-2.0.0.RELEASE.pom; 包含翻译后的API文档:spring-plugin-core-2.0.0.RELEASE-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.springframework.plugin:spring-plugin-core:2.0.0.RELEASE; 标签:spring、core、plugin、springframework、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请放心使用。

【每天学习一点点】Java SPI机制、dubbo spi机制、Springboot自动配置、nacos插件机制以及使用Spring-plugin策略模式

其中工作原理,我们在工程中定义了一个接口A,在启动的时候会去CLASSPATH路径下的META-INF/services中,找到对应接口全路径下的文件文件,该文件内容是返回了一个实现类的全路径名称,这样就会将接口A的实现类给加载到工程中。在设计原则中有一个原则:依赖倒转原则,应该面向接口编程,也就是说应该依赖接口而不是依赖具体的实现,依赖接口,接口具有不同类型的实现,因此可以提高系统的扩展性,如果仅仅是依赖实现,那么就无法进行扩展了。这里的文件名 java.sql.Driver 其实就是一个全路径接口。

路漫漫其修远兮 吾将上下而求索 2241

spring-plugin-core-1.2.0.RELEASE-API文档-中文版.zip

赠送jar包:spring-plugin-core-1.2.0.RELEASE.jar; 赠送原API文档:spring-plugin-core-1.2.0.RELEASE-javadoc.jar; 赠送源代码:spring-plugin-core-1.2.0.RELEASE-sources.jar; 包含翻译后的API文档:spring-plugin-core-1.2.0.RELEASE-javadoc-API文档-中文(简体)版.zip 对应Maven信息:groupId:org.springframework.plugin,artifactId:spring-plugin-core,version:1.2.0.RELEASE 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请放心使用。

spring-plugin-core-3.0.0.jar中文-英文对照文档.zip

1、压缩文件中包含: 中文-英文对照文档、jar包下载地址、Maven依赖、Gradle依赖、源代码下载地址。 2、使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 3、特殊说明: (1)本文档为人性化翻译,精心制作,请放心使用; (2)只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; (3)不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 4、温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件。 5、本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册。

Java热部署进阶:拆解Hotswap Agent的FatJar与Core模式,如何为你的Spring Boot项目提速?

本文深入解析Hotswap Agent的FatJar与Core模式,帮助Java开发者优化Spring Boot项目的热部署效率。通过对比JDK8和JDK11的配置差异,详细介绍了两种模式的应用场景与性能影响,提供实战调优建议,显著提升开发速度。特别适合需要频繁修改代码的Spring Boot开发者。

weixin_28739079的博客 138

labview汽车电子通用测试程序架构,CAN通讯上位机

结合做过的汽车电子测试项目,车身控制器测试,CAN网络模块测试,电机控制器功能测试,汽车仪表盘视觉及功能测试、电气盒功能测试、EOL下线检测、车用空调控制器功能测试等项目,结合实际项目,整理编写的一个汽车电子,通用测试架构,包含项目的讲解等。6、数据保存 、数据处理、 曲线显示 、报警处理等。7、CAN总线故障信息监控及记录保存。2、参数设置(CAN端口及参数)5、CAN通讯+数据解析。

ali2805486883的博客 2758

HotswapAgent架构深度解析:Java运行时类热交换实现原理与最佳实践

HotswapAgent作为Java生态系统中高性能的运行时类热交换框架,通过创新的字节码操作技术和插件化架构,实现了Java应用在运行时无需重启即可实时更新代码的能力。本文将深入解析其核心架构设计、热交换实现机制,并提供实际开发中的最佳实践指南。 ## 技术背景与核心价值 传统的Java开发流程中,每次代码修改都需要重启应用,这严重影响了开发效率。HotswapAgent通过结合DCEVM(

gitblog_00213的博客 466

Kriging代理模型理论相关推导

代理模型,Kriging,加点准则

森屹的博客 1万+

工业模型导入Unity实战:从ProE/SolidWorks到实时渲染的完整流程

在工业仿真、数字孪生和VR/AR应用开发中,将高精度工程模型导入实时渲染引擎是一个常见的技术挑战。其核心原理在于参数化工程软件与实时渲染引擎的数据结构差异:前者基于精确的B-rep边界表示和特征树,后者依赖轻量化的三角网格与材质贴图。这一转换的技术价值在于实现工程数据的可视化与交互化,为产品展示、虚拟培训和工厂仿真等应用场景提供基础。通过数据翻译与优化流程,特别是利用3ds Max或Blender作为中转站进行网格优化与UV展开,能够有效解决模型破面、材质丢失和性能问题。本文聚焦于ProE(Creo)和So

weixin_33050117的博客 344

Spring 4与Struts 2项目基于XML的集成实战

Spring 4与Struts 2项目基于XML的集成实战。为什么要写这篇Hello World级别的文章。大约十年前,我开始使用Spring 2和Struts 1开发Web应用,构建工具使用的是Ant。早些年,把多个框架集成在一起并不容易,各框架间的兼容性也没有现在这么好。不管怎么样,这些基础的框架伴随我们多年。如今十年过去了,沧海桑田,Spring框架和Struts框架都经过了无数个版本的迭代和重构,我重新做一次

chszs的专栏 5544

H无穷控制学习笔记——加权灵敏度H无穷控制问题

一、加权灵敏度H无穷问题 系统结构如上图所示。被控对象P的状态空间方程为(Ap,Bp,Cp,DpA_p,B_p,C_p,D_pAp​,Bp​,Cp​,Dp​),加权函数W1的状态空间方程为(A1,B1,C1,D1A_1,B_1,C_1,D_1A1​,B1​,C1​,D1​),加权函数W2的状态空间方程为(A2,B2,C2,D2A_2,B_2,C_2,D_2A2​,B2​,C2​,D2​),加权函数W3的状态空间方程为(A3,B3,C3,D3A_3,B_3,C_3,D_3A3​,B3​,C3​,D3​)。

一饮丶一啄的博客 4350

HotswapAgent深度解析:Java运行时类热交换零重启架构揭秘

Java开发者在日常开发中经常面临一个共同的痛点:每次修改代码后都需要重启应用服务器,等待漫长的启动时间,这种"修改-重启-等待"的循环严重影响了开发效率。HotswapAgent作为Java运行时类热交换的开源项目,通过字节码动态重定义技术实现了零重启开发体验,让开发者能够在不重启应用的情况下实时更新代码,极大提升开发效率。本文将深度解析HotswapAgent的架构设计、核心原理和实战应用,帮

gitblog_00229的博客 485

基于Termux的Android平台OpenClaw部署:移动端AI助理实现

本文介绍了在Android设备上通过Termux部署OpenClaw AI助理的方案。Android设备的便携性、Termux提供的完整Linux环境以及多样化的硬件配置使其成为理想的部署平台。文章详细分析了不同级别Android设备的硬件规格(从入门级到旗舰级),并提供了最低/推荐配置要求。部署步骤包括Termux安装初始化、Python环境配置以及性能优化建议。该方案充分利用Android设备的传感器和电池供电优势,为移动办公、学习等场景提供了低成本、高便携性的AI助理解决方案。

博客 3015

层层剖析,让你彻底搞懂Self-Attention、MultiHead-Attention和Masked-Attention的机制和原理

本文内容 本文基于李宏毅老师对 Self-Attention 的讲解,进行理解和补充,并结合Pytorch代码,最终目的是使得自己和各位读者更好的理解Self-Attention 李宏毅Self-Attention链接: https://www.youtube.com/watch?v=hYdO9CscNes PPT链接见视频下方 通过本文的阅读,你可以获得以下知识: 什么是Self-Attention,为什么要用Self-Attention? Self-Attention是如何做的? Self-Atten

iioSnail的博客 2万+

使用spring插件实现策略模式

策略模式是一种行为设计模式,可让您定义一系列算法/实现并允许在运行时选择它们。 假设我们有一个支持不同支付类型的支付服务,如信用卡、贝宝、条纹等。我们想根据用户请求决定使用哪种支付方式。让我们开始实施。 添加spring插件依赖: <dependency> <groupId> org.springframework.plugin </groupId> <artifactId> spring-plugin-核心</artifac...

johnhuster的专栏 942

巡检机器人的基于ROS系统的任务管理架构设计总结

本文探讨了基于ROS(机器人操作系统)的工业巡检机器人任务管理架构设计,提出分层闭环方案。架构围绕稳、准、活、扩四大目标,分为感知层(多源数据融合)、调度层(智能决策)、执行层(动作控制)和数据层(存储交互)。关键技术包括ROS2实时性优化、功能包复用和多机器人协同调度。实践案例显示,该架构在电力巡检中使任务完成率达99%,在化工园区实现95%覆盖率。当前挑战包括SLAM地图漂移和多机通信延迟,未来可通过语义SLAM和区域通信优化。

start_up_go的博客 476

SpringBoot 插件化开发模式,强烈推荐!

点击关注公众号:互联网架构师,后台回复2T获取2TB学习资源!上一篇:Alibaba开源内网高并发编程手册.pdf一、前言插件化开发模式正在很多编程语言或技术框架中得以广泛的应用实践,比如大家熟悉的jenkins,docker可视化管理平台rancher,以及日常编码使用的编辑器idea,vscode等,随处可见的带有热插拔功能的插件,让系统像插了翅膀一样,大大提升了系统的扩展性和伸缩性,也拓展...

emprere的博客 1151

内部函数方式获取工序包容盒(最低点和最高点)PTHDSP_ask_box

内部函数方式获取工序包容盒(最低点和最高点)PTHDSP_ask_box。

成长需要沉淀。 397

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Swagger3和SpringBoot搭配,spring-plugin-core报错

错误详情如下 *************************** APPLICATION FAILED TO START *************************** Description: An attempt was made to call the method org.springframework.plugin.core.PluginRegistry.getPluginFor(Ljava/lang/Object;)Ljava/util/Optional; but it does

跑码场 7376

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Spring Plugin 的使用

配置@EnablePluginRegistries注解,可以配置多个Class类型每一个Class类型都创建一个类型为PluginRegistry(具体实现类为OrderAwarePluginRegistry)的Bean,将此Class类型的所有Bean都添加到此PluginRegistry对象中后续可以通过每一个PluginRegistry对象获取到其内部的所有Plugin对象。

Curtisjia的博客 2622

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

springboot集成swagger3,spring-plugin-core报错

springboot集成knife4j的时候3.0.2版本出现了以下问题: An attempt was made to call a method that does not exist. The attempt was made from the following location: springfox.documentation.schema.plugins.SchemaPluginsManager.viewProvider(SchemaPluginsManager.java:95)

weixin_44509615的博客 1770

springboot起步依赖

Spring Boot 1.3.0所支持的库依赖 Group ID Artifact ID 版本号 antlr ...

fenlin88l的博客 1981

SpringBoot-插件化以及springboot扩展接口

SpringBoot-插件化以及springboot扩展接口

usa_washington的博客 1519

SpringBoot配置swagger(3.0.0)及遇到的Bug(spring-plugin-core导包冲突)

SpringBoot配置swagger(3.0.0)及遇到的Bug 一、swagger的配置 1、在pom.xml里添加swagger依赖,如下: <!-- 配置swagger --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</versio

qq_45369827的博客 2106
乌托拉赛文
博客等级 码龄14年 3粉丝 1原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值