还在为发版头疼?SpringBoot 插件化动态类加载方案真香!
推荐关注
哈喽,各位新来的小伙伴们,大家好!由于公众号做了改版,为了保证公众号的资源能准时推送到你手里,大家记得将后端君的公众号 加星标置顶 ,在此真诚的表示感谢~
编辑:后端妹 | 来源:Java知音
上一篇:一个很酷的企业级脚手架系统!
正文
大家好,我是栈哥。
背景
我之前的一家公司是做物联网相关的,当时有一个长期任务,就是对接各个厂家的各类设备。一开始我们都把这些对接设备的代码直接写在服务里面,当然也用了一些设计模式,抽象了统一的接口,所以编码相关的部分其实没有什么大问题。
但是当我们要上线一个新对接的设备或协议的时候,测试的工作量就会比较大,因为从代码的层面来说只是添加了几个类,而从功能模块的层面来说代码有改动就需要重新测试。
当时我就在想,能不能把主业务和对接业务拆分开,主业务的代码没有变动就不需要重复测试了。对接业务以插件的方式集成上去不影响主业务,另外就算对接业务上线之后发现了问题,也能通过可插拔的方式快速优化,不需要重新发布整个服务。
框架介绍
基于当时的想法就有了
Concept Plugin 2GitHub传送门:
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相关的功能
publicclassSpringPluginimplementsCustomPlugin, ApplicationContextAware{@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后端技术
夜雨聆风





