前言:请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i

背景:

在Java代码中当我们需要一个Bean对象,通常会使用spring中@Autowired注解,用来自动装配对象。

在Groovy中不能使用@Autowired(autowired是在spring启动后注入的,此时还未加载groovy代码,故无法注入)

一、使用BeanFactoryPostProcessor注入Bean:

它与 BeanPostProcessor接口类似,可以对bean的定义(配置元数据)进行处理;也就是spring ioc运行BeanFactoryPostProcessor在容器实例化任何其他的bean之前读取配置元数据,并有可能修改它;如果业务需要,可以配置多个BeanFactoryPostProcessor的实现类,通过"order"控制执行次序(要实现Ordered接口)。

第一步:创建实现SpringUtils 接口工具(组件)来获取spring bean

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component; @Component
public class SpringUtils implements BeanFactoryPostProcessor { /** Spring应用上下文环境 \*/
private static ConfigurableListableBeanFactory beanFactory; @Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
{
SpringUtils.beanFactory = beanFactory;
}
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException
{
return (T) beanFactory.getBean(name);
}
public static <T> T getBean(Class<T> clz) throws BeansException
{
T result = (T) beanFactory.getBean(clz);
return result;
}
}

第二步:创建Groovy脚本装载类,动态解析脚本为Class

package com.example.groovy.testgroovy.task;

import groovy.lang.GroovyClassLoader;

public class GroovyUtils {

    private final static ClassLoader classLoader = GroovyUtils.class.getClassLoader();//获取当前类装载器
//ClassLoader:就是类的装载器,它使JVM可以动态的载入Java类,JVM并不需要知道从什么地方(本地文件、网络等)载入Java类,这些都由ClassLoader完成。 public final static GroovyClassLoader groovyClassLoader = new GroovyClassLoader(classLoader);
//GroovyClassLoader:负责在运行时编译groovy源代码为Class的工作,从而使Groovy实现了将groovy源代码动态加载为Class的功能。 /**
* .
* 获取实例化对象
* @param script groovy脚本内容
* @param <T>
* @return
* @throws IllegalAccessException
* @throws InstantiationException
*/
public static <T> T instanceTaskGroovyScript(String script) throws IllegalAccessException, InstantiationException {
Class taskClz = groovyClassLoader.parseClass(script);
T instance = (T) taskClz.newInstance();
return instance;
}
}

第三步:读取脚本内容,执行脚本

@Slf4j
@Component
public class CallAnalysisGroovyTask { /**
* .
* 读取脚本内容
*
* @return
*/
public String getGroovy() {
String context = "";
try {
String path = "E:\\IDEAFile\\testgroovy\\src\\main\\resources\\groovy\\LoadBean.groovy";
context = FileUtils.readFileToString(new File(path));//将脚本内容转为字符串
} catch (IOException e) {
log.error("file is not found[{}]", e);
}
return context;
} /**
* .
* 执行groovy脚本
*
* @param script
*/
public void execGroovy(String script) {
try {
Runnable runnable = GroovyUtils.instanceTaskGroovyScript(script);//获取实例对象
runnable.run();//调用脚本方法
} catch (Exception t) {
log.error("execGroovy file {} error", script);
}
}
}

第四步:在resources目录下创建.groovy文件

@Slf4j
class LoadBean implements Runnable { /**
* .
* Groovy获取Bean
*/
@Override
void run() {
log.info("Groovy开始执行,当前类{}", this.getClass())
ScriptService service = SpringUtils.getBean(ScriptService.class)
log.info("ApplicationContext获取对象[{}]", service.class)
List<Script> item = service.findAll()//执行bean中数据查询方法
for (Script s : item) {
log.info("创建人:[{}],规则id:[{}],名称:[{}]", s.getCreatePerson(), s.getRuleId(), s.getScriptName())
}
log.info("Groovy结束执行,当前类{}", this.getClass())
}
}

第五步:实例化脚本,执行方法

    @GetMapping("/loadBean")
public void loadBean(){
String script = CallAnalysisGroovyTask.getGroovy(); //获取脚本
CallAnalysisGroovyTask.execGroovy(script);//实例化脚本,执行方法
log.info("数据查询成功...");
}

脚本运行结果:

二、使用ApplicationContext注入Bean

它是spring继BeanFactory之外的另一个核心接口或容器,允许容器通过应用程序上下文环境创建、获取、管理bean。为应用程序提供配置的中央接口。在应用程序运行时这是只读的,但如果实现支持这一点,则可以重新加载。

第一步:修改项目启动类,获得ApplicationContext

@SpringBootApplication
public class TestgroovyApplication { //获取应用程序上下文环境
private static ApplicationContext applicationContext; public static void main(String[] args) {
applicationContext = SpringApplication.run(TestgroovyApplication.class, args);
}

第二步:修改resources目录下创建的.groovy文件

    /**
* .
* Groovy获取Bean
*/
@Override
void run() {
log.info("Groovy开始执行,当前类{}", this.getClass())
ScriptService service = TestgroovyApplication.applicationContext.getBean(ScriptService.class)
log.info("ApplicationContext获取对象[{}]", service.class)
List<Script> item = service.findAll()//执行bean中数据查询方法
for (Script s : item) {
log.info("创建人:[{}],规则id:[{}],名称:[{}]", s.getCreatePerson(), s.getRuleId(), s.getScriptName())
}
log.info("Groovy结束执行,当前类{}", this.getClass())
}

脚本运行结果:

参考连接

Groovy获取Bean两种方式(奇淫技巧操作)的更多相关文章

  1. Java执行groovy脚本的两种方式

    记录Java执行groovy脚本的两种方式,简单粗暴: 一种是通过脚本引擎ScriptEngine提供的eval(String)方法执行脚本内容:一种是执行groovy脚本: 二者都通过Invocab ...

  2. Spring 获取bean 几种方式

    转载自: http://www.cnblogs.com/luoluoshidafu/p/5659574.html 1.读取xml文件的方式,这种在初学入门的时候比较适用 . ApplicationCo ...

  3. 将音频文件转二进制分包存储到Redis(奇淫技巧操作)

    功能需求: 一.获取本地音频文件,进行解析成二进制数据音频流 二.将音频流转化成byte[]数组,按指定大小字节数进行分包 三.将音频流分成若干个包,以List列表形式缓存到redis数据库中 四.从 ...

  4. @Autowired获取配置文件中被注入实例的两种方式

    一.说明 二.那么在JavaBean中如何通过@Autowired获取该实例呢?有两种方式: 1.直接获取 @RunWith(SpringJUnit4ClassRunner.class) @Conte ...

  5. Spring定义Bean的两种方式:和@Bean

    前言:    Spring中最重要的概念IOC和AOP,实际围绕的就是Bean的生成与使用. 什么叫做Bean呢?我们可以理解成对象,每一个你想交给Spring去托管的对象都可以称之为Bean. 今天 ...

  6. 获取Executor提交的并发执行的任务返回结果的两种方式/ExecutorCompletionService使用

    当我们通过Executor提交一组并发执行的任务,并且希望在每一个任务完成后能立即得到结果,有两种方式可以采取: 方式一: 通过一个list来保存一组future,然后在循环中轮训这组future,直 ...

  7. strus2中获取表单数据 两种方式 属性驱动 和模型驱动

    strus2中获取表单数据 两种方式 属性驱动 和模型驱动 属性驱动 /** * 当前请求的action在栈顶,ss是栈顶的元素,所以可以利用setValue方法赋值 * 如果一个属性在对象栈,在页面 ...

  8. Express全系列教程之(四):获取Post参数的两种方式

    一.关于POST请求 post方法作为http请求很重要的一部分,几乎所有的网站都有用到它,与get不同,post请求更像是在服务器上做修改操作,它一般用于数据资源的更新.相比于get请求,post所 ...

  9. java动态获取WebService的两种方式(复杂参数类型)

    java动态获取WebService的两种方式(复杂参数类型) 第一种: @Override public OrderSearchListRes searchOrderList(Order_Fligh ...

随机推荐

  1. 菜鸡的Java笔记 第二十六 - java 内部类

    /*    innerClass        从实际的开发来看,真正写到内部类的时候是在很久以后了,短期内如果是自己编写代码,几乎是见不到内部类出现的        讲解它的目的第一个是为了解释概念 ...

  2. 【linux系统】java环境搭建

    搭建步骤 1.安装java : 上传java安装包到linux系统----- rz jdk-8u202-linux-x64.tar.gz jdk下载地址:https://www.oracle.com/ ...

  3. ASP.NET Core 学习笔记 第五篇 ASP.NET Core 中的选项

    前言 还记得上一篇文章中所说的配置吗?本篇文章算是上一篇的延续吧.在 .NET Core 中读取配置文件大多数会为配置选项绑定一个POCO(Plain Old CLR Object)对象,并通过依赖注 ...

  4. [loj6734]图上的游戏

    考虑原图是一条链的情况-- 思路:随机一个点$x$,将其所在段(边集)再划分为两段,重复此过程即可得到该链 实现上,(从左到右)维护每一段的左端点和边集,二分找到最后一个删除后$x$到根不连通的段,那 ...

  5. Git操作: git commit代码后,如何撤回且保留commit的代码

    git commit代码后,但是没有push之前,如果发现提交的代码有一个部分是有问题的,或者commit message写的太随便了想改一下,以下命令会帮到你 git reset HEAD^ 敲击该 ...

  6. C++构造函数写法

    笔记 class complex{ public: complex (double r = 0, double i = 0) : re(r), im(i) {} private: double re, ...

  7. Codeforces 997E - Good Subsegments(线段树维护最小值个数+历史最小值个数之和)

    Portal 题意: 给出排列 \(p_1,p_2,p_3,\dots,p_n\),定义一个区间 \([l,r]\) 是好的当且仅当 \(p_l,p_{l+1},p_{l+2},\dots,p_r\) ...

  8. 洛谷 P5644 - [PKUWC2018]猎人杀(分治+NTT)

    题面传送门 很久之前(2020 年)就听说过这题了,这么经典的题怎么能只听说而亲自做一遍呢 首先注意到每次开枪打死一个猎人之后,打死其他猎人概率的分母就会发生变化,这将使我们维护起来非常棘手,因此我们 ...

  9. Admixture的监督分群(Supervised analysis)

    目录 说明 实战 说明 Admixture通过EM算法一般用于指定亚群分类:或者在不知材料群体结构背景下,通过迭代交叉验证获得error值,取最小error对应的K值为推荐亚群数目.如果我们预先已知群 ...

  10. 37-Invert Binary Tree

    Invert Binary Tree My Submissions QuestionEditorial Solution Total Accepted: 87818 Total Submissions ...