Groovy獲取Bean兩種方式(奇淫技巧操作)

南國以南i發表於2021-12-13

前言:請各大網友尊重本人原創知識分享,謹記本人部落格:南國以南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())
    }

指令碼執行結果:

參考連線

相關文章