概述
模块化开发的方式有很多 基于rest、webservice 接口 或者服务器集群结合单点登录或者spring cloud 微服务等方式 。无非就是要实现 在不影响现有系统正常运行的情况下 上线 或者下线某些功能模块。更新系统的时候不影响正常不在更新范围内的功能。保证系统稳定。
下面我说一种基于spring IOC 方式实现的动态加载卸载jar文件 来实现模块化开发的功能。
这种方式 下各个模块之间的解耦的 他们在一个 spring factory基础平台下被独立加载 互相之间共享基础平台下的 公有方法 和类库,同时各个模块之间拥有自己独立的第三方jar 或者类库。实现一种 低耦合的模块化。
本次只分享部分核心代码 具体如何切合自己的业务逻辑 还需要各位考量。
核心代码主要是两个类和一个方法
ModuleBeanFactory 类
这个类继承 org.springframework.beans.factory.support.DefaultListableBeanFactory 用于存放当前模块的所有bean对象
构造函数
public ModuleBeanFactory(DefaultListableBeanFactory parentBeanFactory) {
this.parentBeanFactory=parentBeanFactory;
}
构造函数中的 parentBeanFactory 是 基础平台的 beanFactory。
@Override
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
if(this.containsBeanDefinition(name)){
return super.doGetBean(name, requiredType, args, typeCheckOnly);
}
return parentBeanFactory.getBean(name,requiredType,args);
}
@Override
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
return super.getBeanDefinition(beanName);
}
重写 doGetBean 获取bean对象优先从当前模块的beanfactory中获取 如果当前模块中不存在那么从 基础平台的beanfatory中获取。
这样实现了各个模块之间 共享使用基础平台beanfactory的 bean对象 同时也能使用自己独立加载的bean对象。
ModuleContext 类
这个类主要是用于 创建spring 上下文
继承 org.springframework.context.annotation.AnnotationConfigApplicationContext
只有一个构造函数
public ModuleContext(ModuleBeanFactory beanFactory) {
super(beanFactory);
}
loadModule 方法
主要用于从磁盘中读取jar文件 并加载到 ModuleContext 和 ModuleBeanFactory 中。
@Autowired
private Environment environment;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.act = applicationContext;
}
public void loadModule (){
//创建 beanFactory
ModuleBeanFactory beanFactory=
new ModuleBeanFactory(
//从 基础类的 applicationContext 获取 beanFactory
//applicationContext 获取方法
((AnnotationConfigServletWebServerApplicationContext) act)
.getDefaultListableBeanFactory());
GenericBeanDefinition definition = new GenericBeanDefinition();
definition.setBeanClass(ConfigurationPropertiesBindingPostProcessor.class);
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
beanFactory.registerBeanDefinition(ConfigurationPropertiesBindingPostProcessor.BEAN_NAME, definition);
ModuleContext applicationContext=new ModuleContext(beanFactory);
//获取父节点 类加载器
URLClassLoader ucl=(URLClassLoader) act.getClassLoader();
URL[] urls=ucl.getURLs();
//加载文件所在路径
// 包含 d:datatest 下的 jar 包 和 d:datatest\lib 下的 第三方jar包
String baseDir="d:\data\test";
String packages="com.test";// 包文件所在路径
//加载 基础平台的 jar 包 和 模块化的jar 包 加载遵循双亲委派机制 基础平台有的包 模块里不能重复加载
StandardExecutorClassLoader classLoader = new StandardExecutorClassLoader(baseDir,
urls, ucl);
applicationContext.setClassLoader(classLoader);
//设置spring 扫描包路径
applicationContext.scan(packages);
// 加载 基础平台的 配置文件
applicationContext.setEnvironment((StandardServletEnvironment)environment);
applicationContext.refresh();
//启动这个applicationContext
applicationContext.start();
//剩下的逻辑根据业务需要来做 比如获取一个 bean对象
applicationContext.getBean("beanName");
或者可以吧这个
}
以上就是模块化 的核心代码部分 。
关于如何父 子 lassloader共享代码没用出来 具体看源码
源码位置
源码位置:(代码有些问题 不在提供 )
具体在
ahead-frame-schedule 下的 ahead-schedule-modules 模块下
如果有不明白可以联系我。
最后
以上就是花痴自行车为你收集整理的利用spring IOC 实现 模块化开发 动态加载 jar包(包括第三方)不需要重启的全部内容,希望文章能够帮你解决利用spring IOC 实现 模块化开发 动态加载 jar包(包括第三方)不需要重启所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复