• 极客专栏正式上线!欢迎访问 https://www.jikewenku.com/topic.html
  • 极客专栏正式上线!欢迎访问 https://www.jikewenku.com/topic.html

利用SPRING管理热加载的GROOVY对象!

技术杂谈 勤劳的小蚂蚁 4个月前 (12-30) 115次浏览 已收录 0个评论 扫描二维码

原因

最近做的项目属于数据分析类型,要求数据分析功能做到快速上线。该项目当前使用的语言是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. classHello {
  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. publicclassHelloService {
  4.    publicString hello() {
  5.        return"now hello";
  6.    }
  7. }
第一步,需要拿到Spring上下文 ApplicationContext。这个有很多种实现,比如继承ApplicationContextAware接口等。
第二步,获取到编译后的脚本,如下。
  1. //从数据库中获取到脚本内容
  2. String scriptContent = "......";
  3. //编译
  4. Class clazz = newGroovyClassLoader().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-

丨极客文库, 版权所有丨如未注明 , 均为原创丨
本网站采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行授权
转载请注明原文链接:利用SPRING管理热加载的GROOVY对象!
喜欢 (0)
[247507792@qq.com]
分享 (0)
勤劳的小蚂蚁
关于作者:
温馨提示:本文来源于网络,转载文章皆标明了出处,如果您发现侵权文章,请及时向站长反馈删除。

您必须 登录 才能发表评论!

  • 精品技术教程
  • 编程资源分享
  • 问答交流社区
  • 极客文库知识库

客服QQ


QQ:2248886839


工作时间:09:00-23:00