QLexpress实现Spring的融合--Set方法注入

QLexpress实现Spring的融合–Set方法注入

对于qlExpress脚本引擎来说,能否调用spring bean的方法?怎么调用?是一个非常常见的问题。本文章主要讲述我是如何实现Spring注入属性(Set方法)与QLexpress组件的融合,请阅读下面的案例。

第一步:定义变量并进行变量的封装

这里我创建了UserDo对变量进行封装,保证代码的灵活性。详细代码如下:

public class UserDO {
    private String nick;

    private Long userId;

    private Date gmtCreate;

    private String position;

    private Double salary;

    public String getNick() {
        return nick;
    }

    public void setNick(String nick) {
        this.nick = nick;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public Date getGmtCreate() {
        return gmtCreate;
    }

    public void setGmtCreate(Date gmtCreate) {
        this.gmtCreate = gmtCreate;
    }

    public String getPosition() {
        return position;
    }

    public void setPosition(String position) {
        this.position = position;
    }

    public Double getSalary() {
        return salary;
    }

    public void setSalary(Double salary) {
        this.salary = salary;
    }
}

第二步:利用Set方法向Spring容器内注入Bean属性

这里采用的是利用Set方法将属性注入到Spring容器中,Spring配置文件会自动配置属性注入,代码如下:

public class BizLogicBean {
    public UserDO getUserInfo(String nick) {
        if (nick.equals("小王")) {
            UserDO userDO = new UserDO();
            userDO.setNick(nick);
            userDO.setGmtCreate(new Date());
            userDO.setUserId(10086L);
            userDO.setPosition("salesman");
            userDO.setSalary(5000.0);
            return userDO;
        } else if (nick.equals("马总")) {
            UserDO userDO = new UserDO();
            userDO.setNick(nick);
            userDO.setGmtCreate(new Date());
            userDO.setUserId(1L);
            userDO.setPosition("boss");
            userDO.setSalary(999999999999.0);
            return userDO;
        }
        return null;
    }
}

第三步:获取Spring容器中的属性值

紧接着上一步,获取到Spring容器中的属性值,代码如下:

public class QLExpressContext extends HashMap<String, Object> implements IExpressContext<String, Object> {
    private final ApplicationContext applicationContext;

    public QLExpressContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public QLExpressContext(Map<String, Object> properties, ApplicationContext applicationContext) {
        super(properties);
        this.applicationContext = applicationContext;
    }

    /**
     * 抽象方法:根据名称从属性列表中提取属性值
     */
    @Override
    public Object get(Object name) {
        Object result;
        result = super.get(name);
        try {
            if (result == null && this.applicationContext != null
                    && this.applicationContext.containsBean((String)name)) {
                // 如果在Spring容器中包含bean,则返回String的Bean
                result = this.applicationContext.getBean((String)name);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return result;
    }
}

第四步:通过扩展IExpressContext->QLExpressContext,打通spring容器

这一步是关键,通过runner初始化获取到spring容器中的属性值,代码如下:

public class QlExpressUtil implements ApplicationContextAware {
    private static final ExpressRunner runner;

    static {
        runner = new ExpressRunner();
    }

    private static boolean isInitialRunner = false;
    private ApplicationContext applicationContext;// spring上下文

    /**
     * @param statement 执行语句
     * @param context   上下文
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public Object execute(String statement, Map<String, Object> context) throws Exception {
        initRunner(runner);
        IExpressContext expressContext = new QLExpressContext(context, applicationContext);
        return runner.execute(statement, expressContext, null, true, false);
    }

    private void initRunner(ExpressRunner runner) {
        if (isInitialRunner) {
            return;
        }
        synchronized (runner) {
            if (isInitialRunner) {
                return;
            }
            try {
                runner.addFunctionOfServiceMethod("读取用户信息", applicationContext.getBean("bizLogicBean"), "getUserInfo",
                    new Class[] {String.class}, null);
                runner.addMacro("判定用户是否vip", "userDO.salary>200000");

            } catch (Exception e) {
                throw new RuntimeException("初始化失败表达式", e);
            }
        }
        isInitialRunner = true;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

第五步:测试是否成功引用到spring容器中的Bean属性

利用Junit对代码块进行测试,代码如下:

public class SpringDemoTest extends UnitilsJUnit4 {
    @SpringBeanByName
    private QlExpressUtil qlExpressUtil;

    @Test
    public void testScript() throws Exception {
        String express = ""
            + "if(bizLogicBean.getUserInfo(nick)!=null) {"
            + "    userDO = bizLogicBean.getUserInfo(nick);"
            + "    if(userDO.salary>20000 && userDO.salary<20000) {"
            + "        System.out.println('高级客户:'+userDO.nick);"
            + "    } else if(userDO.salary>=200000) {"
            + "        System.out.println('vip客户:'+userDO.nick);"
            + "    } else {"
            + "        System.out.println('普通客户:'+userDO.nick);"
            + "    }"
            + "} else {"
            + "    System.out.println('用户信息不存在');"
            + "}";

        Map<String, Object> context = new HashMap<>();
        context.put("nick", "马总");
        qlExpressUtil.execute(express, context);
        context.put("nick", "小王");
        qlExpressUtil.execute(express, context);
        context.put("nick", "XXX");
        qlExpressUtil.execute(express, context);
    }

    @Test
    public void testScript2() throws Exception {
        String express = ""
            + "userDO = 读取用户信息(nick);"
            + "if(userDO != null) {"
            + "    if(判定用户是否vip)"//直接中文代码,这就很好理解了!!
            + "        System.out.println('vip客户:' + nick);"
            + "} else {"
            + "    System.out.println('用户信息不存在,nick:' + nick);"
            + "}";

        Map<String, Object> context = new HashMap<>();
        context.put("nick", "马总");
        qlExpressUtil.execute(express, context);

        context.put("nick", "小王");
        qlExpressUtil.execute(express, context);

        context.put("nick", "XXX");
        qlExpressUtil.execute(express, context);
    }
}

testScript测试结果:

testScript2测试结果:

PS:小编是引用GitHub上面的源码举例,希望大家能够理解其中的原理,有问题请联系QQ:1443497132

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wsgodlike

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值