Jarslink Demo源码
https://github.com/baidaguo/jarslink
Jarslink 简介
JarsLink是一个基于JAVA的模块化开发框架,它提供在运行时动态加载模块(JAR包)、卸载模块和模块间调用的API。
优点
隔离性
类隔离:框架为每个模块的Class使用单独的ClassLoader来加载,每个模块可以依赖同一种框架的不同的版本。
实例隔离:框架为每个模块创建了一个独立的Spring上下文,来加载模块中的BEAN,实例化失败不会影响其他模块。
资源隔离:后续会支持模块之间的资源隔离,每个模块使用独立的CPU和内存资源。
动态性
动态发布:模块能在运行时动态加载到系统中,实现不需要重启和发布系统新增功能。支持突破双亲委派机制,在运行时加载父加载器已经加载过的类,实现模块升级依赖包不需要系统发布。
动态卸载:模块能在运行时被动态卸载干净,实现快速下线不需要功能。
应用背景
微服务集成测试, 目前一个微服务是一个FAT
JAR,如果有几十个微服务,则需要启动很多进程,DEBUG端口会很多,使用JarsLink框架合并FAT
JAR,再路由请求到其他JAR,就可以只启动一个进程进行DEBUG测试。
数据管理中心,数据采集的数据源多,而且每种数据源都需要对接和开发,通过模块化开发,实现一个数据源使用一个模块进行对接。
指标计算系统,每个TOPIC一个模块,把消息转发到模块中进行消息处理。
后台管理系统,几乎每个系统都有后台开发的需求,新建应用则应用数多,维护成本高,
引入模块化开发,一个二级域一个模块来开发后台功能。
目前蚂蚁金服微贷事业部几个系统和几十个模块已经使用JarsLink框架。
下载
官网:https://github.com/alibaba/jarslink
其它途径:https://oss.sonatype.org/#nexus-search;quick~jarslink
项目总体构造
引入依赖
此处jarslink-api选择引入1.6版本以上 由于在每次开发一个Action就要配置文件中加配置文件<beanid=”” name=”” class=”” />,一旦类多了,这样管理比较麻烦,还好在1.6版本中提供了扫描包的功能。
<dependency> <groupId>com.alipay.jarslink</groupId> <artifactId>jarslink-api</artifactId> <version>1.6.1.20180301</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>5.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.0.5.RELEASE</version> <optional>true</optional> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.3</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.3.2</version> </dependency> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>${apache.commons.lang.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.7</version> </dependency> <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>${apache.commons.collections.version}</version> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>17.0</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.5.RELEASE</version> </dependency>
主模块引入子模块jar包
jarslink.xml配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--模块加载引擎--> <bean id="moduleLoader" name="moduleLoader" class="com.alipay.jarslink.api.impl.ModuleLoaderImpl" /> <!--模块管理器--> <bean id="moduleManager" name="moduleManager" class="com.alipay.jarslink.api.impl.ModuleManagerImpl" /> <!--可以通过该对象获取所有模块信息--> <bean id="moduleRefreshScheduler" name="moduleRefreshScheduler" class="com.alibaba.service.ModuleRefreshSchedulerImpl"> <property name="moduleLoader" ref="moduleLoader" /> <property name="moduleManager" ref="moduleManager" /> </bean> </beans>
子模块一配置及Action
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:webflow="http://www.springframework.org/schema/webflow-config" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/webflow-config http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd" default-autowire="byName"> <context:annotation-config/> <!--创建Action--> <bean id="helloWorldAction" class="com.alibaba.action.HelloWorldAction"/> <bean id="welComeAction" class="com.alibaba.action.WelComeAction" /> </beans>
public class HelloWorldAction implements Action<String, String> { @Override public String execute(String s) { return s + ":hello world222"; } @Override public String getActionName() { return "hello-world-action"; } }
public class WelComeAction implements Action<String, String> { @Override public String execute(String s) { return "welcome " + s; } @Override public String getActionName() { return "welcome-action"; } }
子模块二配置及Action
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:webflow="http://www.springframework.org/schema/webflow-config" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/webflow-config http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd" default-autowire="byName"> <context:annotation-config/> </beans>
@Configuration public class StringToLongAction implements Action<String, Long> { @Override public Long execute(String s) { return Long.valueOf(s); } @Override public String getActionName() { return "string-to-long"; } }
编译文件然后导出Jar包 这样一个模块就开发完成(一个模块的Action开发就是这么简单,1.创建自己的Action;2.配置文件中配置bean信息) 对应模块下有自己对应的Action
测试
此处我们选择子模块一HelloAction进行调用测试
运行结果如下
可以看到HelloAction已调用 而后修改完成子模块重新打包jar,并且拷贝到主模块下
更新HelloAction后会实现热插拔动态部署 再次看结果如下: