乐于分享
好东西不私藏

还在为发版头疼?SpringBoot 插件化动态类加载方案真香!

还在为发版头疼?SpringBoot 插件化动态类加载方案真香!

推荐关注

以下文章来源Java后端栈,回复”面试“获面试宝典

哈喽,各位新来的小伙伴们,大家好!由于公众号做了改版,为了保证公众号的资源能准时推送到你手里,大家记得将后端君的公众号 加星标置顶 ,在此真诚的表示感谢~

编辑:后端妹 | 来源:Java知音

上一篇一个很酷的企业级脚手架系统!

正文

大家好,我是栈哥。

背景

我之前的一家公司是做物联网相关的,当时有一个长期任务,就是对接各个厂家的各类设备。一开始我们都把这些对接设备的代码直接写在服务里面,当然也用了一些设计模式,抽象了统一的接口,所以编码相关的部分其实没有什么大问题。

但是当我们要上线一个新对接的设备或协议的时候,测试的工作量就会比较大,因为从代码的层面来说只是添加了几个类,而从功能模块的层面来说代码有改动就需要重新测试。

当时我就在想,能不能把主业务和对接业务拆分开,主业务的代码没有变动就不需要重复测试了。对接业务以插件的方式集成上去不影响主业务,另外就算对接业务上线之后发现了问题,也能通过可插拔的方式快速优化,不需要重新发布整个服务。

框架介绍

基于当时的想法就有了 Concept Plugin 2

GitHub传送门:

https://github.com/Linyuzai/concept/wiki/Concept-Plugin-2

使用

1. 在代码中配置需要提取的插件内容
@EnablePluginConcept@ConfigurationpublicclassPluginConfig{@OnPluginExtractpublicvoidplugin(CustomPlugin plugin){//CustomPlugin 替换为我们业务中自己定义的接口或类即可//匹配到 CustomPlugin 就会回调该方法    }}
  • @EnablePluginConcept用于启用插件功能,也可以标记在启动类上

  • @OnPluginExtract标记在方法上表示插件回调

  • @OnPluginExtract标记的方法只要能被Spring扫描到就行

2. 通过管理页面上传插件

管理页面路径:/concept-plugin/management.html

3. 第三步

没有第三步啦,上面的内容就是全部啦

优势

使用方便

这我不得不说,Spring Boot才是鼻祖,一个注解帮你集成所有功能

咱也是从开发者使用的角度来考虑,能省的都省了,变成了一堆默认配置

另外插件管理也提供了现成的页面,只要点一点就行了,测试运维都能用

学习门槛低

就以上面的示例为例

@EnablePluginConcept@ConfigurationpublicclassPluginConfig{@OnPluginExtractpublicvoidplugin(CustomPlugin plugin){//CustomPlugin 替换为我们业务中自己定义的接口或类即可//匹配到 CustomPlugin 就会回调该方法    }}

除了两个注解@EnablePluginConcept@OnPluginExtract对第一次使用的开发者来说是新的东西(但是很容易理解)

其他的内容都可以不涉及这个框架

包括我们实现的插件,也不需要标记什么注解,实现什么接口,没有任何侵入性

写法自由

有的朋友可能要问了

  • 我们自己定义的方法需不需要什么固定的格式?

  • 会不会因为写法或顺序问题导致拿不到数据?

格式?没有那种东西

咱主打的就是一个 freestyle

什么?你想直接拿到类而不是实例,那就这样写

@EnablePluginConcept@ConfigurationpublicclassPluginConfig{@OnPluginExtractpublicvoidplugin(Class<? extends CustomPlugin> plugin){    }}

什么?一个插件包里面定义了多个插件实现,那就这样写

@EnablePluginConcept@ConfigurationpublicclassPluginConfig{@OnPluginExtractpublicvoidpluginList(List<CustomPlugin> plugins){    }@OnPluginExtractpublicvoidpluginSet(Set<CustomPlugin> plugins){    }@OnPluginExtractpublicvoidpluginArray(CustomPlugin[] plugins){    }}

什么?你平时习惯加范型,那就这样写

@EnablePluginConcept@ConfigurationpublicclassPluginConfig{@OnPluginExtractpublicvoidplugin(List<? extends CustomPlugin> plugins){    }}

什么?插件包里还有一个 Properties 文件想一起读出来,那就这样写

@EnablePluginConcept@ConfigurationpublicclassPluginConfig{@OnPluginExtractpublicvoidplugin(CustomPlugin plugin, Properties properties){    }}

主打一个,你想要啥,你就加啥,所见即所得

精确匹配

有的朋友可能又要问了

插件包不止一个 Properties 文件,想要分开单独读取,可以这样写

@EnablePluginConcept@ConfigurationpublicclassPluginConfig{@OnPluginExtractpublicvoidplugin(@PluginEntry("first.properties") Properties properties,                         @PluginEntry("second.properties") Properties properties) {    }}

@PluginEntry可以用来匹配路径和名称

使用AntPath的风格,如:

  • @PluginEntry("content/**")

  • @PluginEntry(**/**.json)

Spring支持

集成了部分Spring的能力,使用更加方便

插件配置

可以在插件包中添加plugin.properties文件作为插件配置

  • java项目在resources目录下添加即可

  • zip文件在根目录下添加即可

插件配置提供了基于Spring的属性绑定功能

这是我们的插件配置文件

#自定义配置custom.app=${spring.application.name}#支持Spring占位符custom.value=custom

额外注入Plugin通过PluginMetadata进行读取

@EnablePluginConcept@ConfigurationpublicclassPluginConfig{@OnPluginExtractpublicvoidplugin(Plugin plugin){        PluginMetadata metadata = plugin.getMetadata();//可以根据name直接读取        String app = metadata.get("custom.app");        String value = metadata.get("custom.value");//也可以绑定对象        CustomData data = metadata.bind("custom", CustomData.class);    }@DatapublicstaticclassCustomData{private String app;private String value;    }}
自动注入

既然配置部分已经和Spring结合了

那么实例部分也是支持了Spring的依赖注入能力

在实现插件的时候可以直接使用Spring相关的功能

publicclassSpringPluginimplementsCustomPluginApplicationContextAware{@Value("${spring.application.name}")private String applicationName;@Autowiredprivate ApplicationEventPublisher applicationEventPublisher;private ApplicationContext applicationContext;@OverridepublicvoidsetApplicationContext(ApplicationContext applicationContext)throws BeansException {this.applicationContext = applicationContext;    }}

大部分的依赖注入功能都是支持的

支持嵌套或关联依赖

在实现插件的时候有可能需要依赖其他的jar中的类

如果插件依赖的类在我们的主服务中已经存在了那就不需要管

如果在主服务中没有,有下面两种方案:

嵌套依赖

可以把依赖的jar打包进插件包里面,这样就能自动识别

插件依赖

如果被依赖的jar比较通用,很多插件都需要依赖

那么可以把这个jar作为一个基础插件(多个jar可以打包成zip)

在这个基础插件中添加配置plugin.properties

concept.plugin.name=common #插件名称concept.plugin.handler.enabled=false#作为基础插件不进行解析匹配提取

然后在其他的插件包中添加配置plugin.properties

concept.plugin.dependency.names=common #依赖的插件,多个用逗号分隔

这样我们的插件就能加载到基础插件中的类了

可视化页面

为了方便插件管理,我还专门写了一个页面

提供插件上传,下载,加载,卸载,等基础功能

结束

如果大家感兴趣或有需要可以看下更详细的用法 Wiki

https://github.com/Linyuzai/concept/wiki/Concept-Plugin-2

为了跟上AI时代我干了一件事儿,我创建了一个知识星球社群:ChartGPT与副业。想带着大家一起探索ChatGPT和新的AI时代

有很多小伙伴搞不定ChatGPT账号,于是我们决定,凡是这三天之内加入ChatPGT的小伙伴,我们直接送一个正常可用的永久ChatGPT独立账户。

不光是增长速度最快,我们的星球品质也绝对经得起考验,短短一个月时间,我们的课程团队发布了8个专栏、18个副业项目

简单说下这个星球能给大家提供什么:

1、不断分享如何使用ChatGPT来完成各种任务,让你更高效地使用ChatGPT,以及副业思考、变现思路、创业案例、落地案例分享。

2、分享ChatGPT的使用方法、最新资讯、商业价值。

3、探讨未来关于ChatGPT的机遇,共同成长。

4、帮助大家解决ChatGPT遇到的问题。

5、提供一整年的售后服务,一起搞副业

星球福利:

1、加入星球4天后,就送ChatGPT独立账号。

2、邀请你加入ChatGPT会员交流群。

3、赠送一份完整的ChatGPT手册和66个ChatGPT副业赚钱手册。

其它福利还在筹划中... 不过,我给你大家保证,加入星球后,收获的价值会远远大于今天加入的门票费用 !

本星球第一期原价399,目前属于试运营,早鸟价169,每超过50人涨价10元,星球马上要来一波大的涨价,如果你还在犹豫,可能最后就要以更高价格加入了。。

早就是优势。建议大家尽早以便宜的价格加入!

欢迎有需要的同学试试,如果本文对您有帮助,也请帮忙点个 赞 + 在看 啦!❤️

在 GitHub猿 还有更多优质项目系统学习资源,欢迎分享给其他同学吧!

最后给读者整理了一份BAT大厂面试真题,需要的可扫码加微信备注:“面试”获取。

◆ ◆ ◆  ◆ ◆ 

(放到你圈子里,朋友们会感激您)
PS:如果觉得我的分享不错,欢迎大家随手点赞、在看。
本文仅供交流学习 , 版权归属原作者。温馨提示:《Java后端栈》推文内容如有侵权请您告知我们会在第一时间处理或撤销;互联网是一个资源共享的生态圈,我们崇尚分享。
好文推荐:

欢迎添加栈哥个人微信 ysle007  进粉丝群或围观朋友圈

扫码关注带你吊爆Java后端技术

本站文章均为手工撰写未经允许谢绝转载:夜雨聆风 » 还在为发版头疼?SpringBoot 插件化动态类加载方案真香!

评论 抢沙发

7 + 3 =
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
×
订阅图标按钮