利用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:\data\test 下的 jar 包 和 d:\data\test\\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 模块下
如果有不明白可以联系我。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值