我是靠谱客的博主 花痴自行车,最近开发中收集的这篇文章主要介绍利用spring IOC 实现 模块化开发 动态加载 jar包(包括第三方)不需要重启,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

模块化开发的方式有很多 基于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包(包括第三方)不需要重启所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(69)

评论列表共有 0 条评论

立即
投稿
返回
顶部