作者:paleXu的技术博客

来源:https://palexu.github.io/posts/spring-dynamic-load-groovy-bean?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io

原因

最近做的项目属于数据分析类型,要求数据分析功能做到快速上线。该项目当前使用的语言是Java + Groovy。 使用Groovy的原因很简单,因为 Groovy 脚本支持热加载功能。项目中,简单的数据分析工作,如一些统计、排序、过滤等,都放在Groovy里完成。需要上线新的数据分析功能时,只需要编写一个新的脚本,并热加载到JVM中即可。

现在希望将一些数据源访问、数据预处理的工作也放到 Groovy 脚本中完成,并具有这样的功能:项目在线上稳定运行期间,可以通过修改数据库中的脚本来完成新产品的上线。


解决方案

  • PlanA: Java + 热加载 

  • PlanB: Groovy + 热加载

最终选择的方案是PlanB:让 Groovy 脚本需要具有访问数据源、调用rpc服务等等的能力。核心思路是利用Spring对Groovy脚本进行管理。

1、Groovy 脚本保存在数据库中。定时任务不断轮训数据库检测Groovy脚本的更新时间,若有更新,则读取脚本内容,并解析为Class。

2、然后利用Spring提供的工具类BeanDefinitionBuilder,生成BeanDefinition。BeanDefinition中保存了Groovy脚本的meta信息,比如对其他类的依赖。

3、接着,将BeanDefinition放入Spring上下文ApplicationContext中,并调用初始化方法,对bean进行依赖注入。

4、最后,调用context.getBean(“xxx”)拿到该脚本。

当然,需要注意的细节有很多,比如服务降级、安全控制等,这里就不展开说了。

简单实现

Hello.groovy 这是保存在数据库中的Groovy脚本。

  1. import org.springframework.beans.factory.annotation.Autowired

  2. class Hello {

  3.    @Autowired

  4.    HelloService service;

  5.    HelloService getService() {

  6.        return service

  7.    }

  8.    def run() {

  9.        print(service.hello())

  10.    }

  11. }

HelloService.java 这是项目中已经提供的服务,现实项目中可以是访问数据源等功能。

  1. import org.springframework.stereotype.Component;

  2. @Component

  3. public class HelloService {

  4.    public String hello() {

  5.        return "now hello";

  6.    }

  7. }

第一步,需要拿到Spring上下文 ApplicationContext。这个有很多种实现,比如继承ApplicationContextAware接口等。

第二步,获取到编译后的脚本,如下。

  1. //从数据库中获取到脚本内容

  2. String scriptContent = "......";

  3. //编译

  4. Class clazz = new GroovyClassLoader().parseClass(scriptContent);

第三步,将bean放入上下文,并进行依赖注入

  1. BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);

  2. BeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();

  3. context.getAutowireCapableBeanFactory().applyBeanPostProcessorsAfterInitialization(beanDefinition, "hello");

  4. beanFactory.registerBeanDefinition("hello", beanDefinition);

第四步,从上下文中获取Groovy脚本

  1. Hello hello = context.getBean("hello");

  2. hello.run();

  3. //console中应当输出下面内容,此时说明HelloService已经成功注入到groovy脚本中了

  4. //now hello

参考资料

1、Groovy 使 Spring 更出色,第 2 部分 - 在运行时改变应用程序的行为 - 用 Groovy 为 Spring 应用程序添加可动态刷新的 bean

2、动态注入 Bean 到 Spring 容器

3、spring 动态注册 bean 王雁

4、Spring 动态注册 bean 李佳明

-END-

 今日推荐:

推荐一个极客时间的专栏:《深入拆解Java虚拟机》,作者是Oracle高级研究员郑雨迪,在JVM领域也是一位大牛。这个专栏,他会手把手带你入门Java虚拟机,让你系统掌握Java性能分析、调优,修炼进阶必备技能!

限时拼团¥49,原价¥68,立省¥19

扫码即可参与拼团

(很久才做一次降价活动的专栏,可不要错过。

 近期热文:

  • Spring Boot中如何扩展XML请求和响应的支持

  • Java 11正式发布,新特性解读

  • 从一张搞笑图看JavaScript的语法和特性

  • 【辟谣】代码规范固然重要,但是不要再黑程序员了...

  • 研究优雅停机时的一点思考

  • 搞个996或247,你的团队就是互联网团队了?

  • 印象笔记终于支持Markdown了 !你还会再用其他笔记吗?

关注我

点击“阅读原文”,看本号其他精彩内容

利用SPRING管理热加载的GROOVY对象!相关推荐

  1. Spring实现热加载MyBatis 的XML配置文件

    为什么80%的码农都做不了架构师?>>>    package com.myapp.util;import java.io.IOException; import java.lang ...

  2. 京东一面:Spring Boot 如何热加载jar实现动态插件?

    一.背景 动态插件化编程是一件很酷的事情,能实现业务功能的 解耦 便于维护,另外也可以提升 可扩展性 随时可以在不停服务器的情况下扩展功能,也具有非常好的 开放性 除了自己的研发人员可以开发功能之外, ...

  3. Nacos Spring Cloud 实现配置热加载

    0x01:安装 Nacos 下载安装包, https://github.com/alibaba/nacos/releases 从下载 nacos-server-$version.zip 安装包. 解压 ...

  4. Spring Boot + IntelliJ IDEA——自动部署[Spring Boot热部署]+LiveReload[前端自动刷新、热加载]解决方案

    基本概念 spring-boot-devtools: Spring Boot包括一组额外的工具,这些工具可以使应用程序开发体验更加愉快.该spring-boot-devtools模块可以包含在任何项目 ...

  5. spring boot:从零开始搭建一个项目 - day 7 springboot devtools热加载+MybatisPlus配置+kisso从入门到放弃

    spring boot:从零开始搭建一个项目 - day 7 springboot devtools热加载+MybatisPlus配置+kisso从入门到放弃 一.springboot devtool ...

  6. spring boot的热加载(hotswap)

    官网上是叫hotswap,有人翻译成热部署,有人翻译成热加载 个人倾向于使用热加载在这个词,和谷歌翻译的热插拔相似. 关于个人理解 http://www.cnblogs.com/ptqueen/p/8 ...

  7. webpack 热加载你站住,我对你好奇很久了

    使用webpack有一段时间了,其中的模块热加载加快了开发的速度.它无需刷新,只要修改了文件,客户端就立刻立刻做热加载.如何做到?当然理解他的最好的做法就是我们自己做做一遍. 本文关心的是: dev- ...

  8. 热加载和热部署,没听过?看看 Tomcat 是怎么实现的

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者 | 不学无数的程序员 来源 | https://urlify ...

  9. IntelliJ IDEA 2017.3.2 热加载(Hot Swap)

    一.IntelliJ IDEA 自带热加载,修改代码后点击Ctrl + F9即可 缺点:1.Ctrl + F9只对当前类重新编译加载 2.只支持构造代码块的CRUD.方法体内代码修改.资源文件内容的修 ...

最新文章

  1. 如何进行网站主题模型优化_如何进行网站关键词优化
  2. 带宽与码元的关系_带宽、速率(波特率、比特率)和码元宽度简述
  3. 「对抗深度强化学习」是如何解决自动驾驶汽车系统中的「安全性」问题的?...
  4. Java并发编程:深入剖析ThreadLocal
  5. Git多人开发场景模拟
  6. github托管代码
  7. java轩辕剑天之痕游戏攻略_轩辕剑之天之痕游戏攻略大全
  8. 思科asa5515端口映射_Cisco ASA端口映射
  9. java x.length_Java中的length和length()
  10. python virtualenv_python开发之virtualenv与virtualenvwrapper讲解
  11. cobbler get-loaders 错误解决方法
  12. vim莫名假死的解决办法
  13. 面向小姐姐的编程——java面向对象之final、static关键字
  14. 7-31 字符串循环左移 (20 分)
  15. Android8.0 学习(15)---适配Android 8.0
  16. 面试题:老师生日分析过程,能否建模用程序解答?
  17. leetcode记录-罗马数字转整数
  18. Windows 技巧集
  19. Linux系统监视与进程管理
  20. linux挂载硬盘提示我格式化,linux中磁盘格式化挂载使用

热门文章

  1. tomcat 启动报栈溢出 解决方法
  2. POSIX多线程编程-条件变量pthread_cond_t
  3. php文件上传绕过mime类型,文件上传限制绕过技巧
  4. 南京林业大学计算机专升本,2018江苏专转本学校之:南京林业大学
  5. cpu内存调度python_Python/Pycharm内存和CPU分配以提高运行速度?
  6. c语言哈希表电子辞典_关于redis涉及的知识点,C语言如何操作redis
  7. centos 安装2个mysql_CentOs服务器下安装两个个MySql数据库踩坑日记
  8. Tomcat禁用SSLv3和RC4算法
  9. mysql 8.0.21 安装配置方法图文教程
  10. android 时间轴动画教程,android 时间轴(listview实现) 源码