您的位置:首页 > Web前端 > Node.js

问题(已解决):Spring-Expression中,SpelNodeImpl类的子类BeanReference对应什么场景?

2018-10-09 20:47 603 查看

【背景】

在研究SpEL表达式漏洞官方推出的增强方案时发现,官方推出的SimpleEvaluationContext.java对比StandardEvaluationContext.java修改了一些东西。其中一个就是修改了getBeanResolver()方法的实现,将其返回置为空。分析源码以后,我猜测:SimpleEvaluationContext.java重写getBeanResolver()方法的实现,目的是为了禁止在bean中使用表达式。getBeanResolver()方法调用图如下(虚线表示接口或抽象类的方法):

【问题描述】

为了验证这个猜想,我写了一个使用bean中使用SpEL的demo,但是发现demo运行时,并没有构造BeanReference类的实例,更没有调用到BeanReference.getValueInternal()方法以及EvaluationContext.getBeanResolver()方法。因此,BeanReference类的作用是什么呢?在什么情况下才能触发这个类的构造以及BeanReference.getValueInternal()方法的执行呢?
我用来测试的demo如下:
Inventor.java(Bean的java对象)

package com.power.bean;

import java.util.Date;
import java.util.GregorianCalendar;

/**
* @author power
* @date 2018/10/8 下午2:34
*/
public class Inventor {
private String name;
private Date birthday;
private String nationality;
private Object random;

public Inventor() {}

public Inventor(String name, Date birthday, String nationality) {
this.name = name;
this.birthday = birthday;
this.nationality = nationality;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Date getBirthday() {
return birthday;
}

public void setBirthday(Date birthday) {
this.birthday = birthday;
}

public String getNationality() {
return nationality;
}

public void setNationality(String nationality) {
this.nationality = nationality;
}

public Object getRandom() {
return random;
}

public void setRandom(Object random) {
this.random = random;
}
}

bean的配置文件spel01.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

<bean id="test" class="com.power.bean.Inventor">
<!--<property name="random" value="#{T(java.lang.Math).random()*100}"></property>-->
<property name="random" value="1000"></property>
</bean>

<bean id = "Tesla" class="com.power.bean.Inventor">
<!--<property name="name" value="#{test.name}"></property>-->
<property name="name" value="#{'Hello'+ 'World'}"></property>
<!-- <property name="birthday" value="1972-09-01"></property>-->
<property name="nationality" value="Serbian"></property>
<property name="random" value="#{test.random}"></property>
</bean>
测试类test.java:
package com.power.spel;

import com.power.bean.Inventor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.DataBindingPropertyAccessor;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.util.GregorianCalendar;

/**
* @author power
* @date 2018/10/8 下午2:32
*/
public class SpEL {
public void test() {
GregorianCalendar calendar = new GregorianCalendar();
calendar.set(1856,7,9);

//Inventor tesla = new Inventor("Nikola Tesla", calendar.getTime(), "Serbian");
ApplicationContext ctx = new ClassPathXmlApplicationContext("spel01.xml");
Inventor tesla = ctx.getBean("Tesla",Inventor.class);

System.out.println(tesla.getRandom());
}

public static void main(String[] args) {
SpEL demo = new SpEL();
demo.test();
}
}

【实验情况】

最终实验的时候,SpelNodeImpl.getValue()并未调用BeanReference,getValueInternal()的实现,调用的是CompoundExpression.getValueInternal()。且整个执行过程均未调用到BeanReference.getValueInternal()

【问题出现原因】
最后,重新阅读了Spring-Expression的官方文档以后发现:此处的BeanReference的应用场景不是在BeanDefinition中使用表达式,而是允许用户自定义的BeanResolver,处理ExpressionParser.parseExpression(String expression)中的expression。具体说明见:https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#expressions

  1. test.java
package com.power.spel;

import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

/**
* @author power
* @date 2018/10/10 上午10:39
*/
public class BeanReferenceTest {
public void test() {
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setBeanResolver(new MyBeanResolver());

Object bean = parser.parseExpression("&foo").getValue(context);
System.out.println(bean);
}

public static void main(String[] args) {
BeanReferenceTest demo = new BeanReferenceTest();
demo.test();
}
}
  1. MyBeanResolver.java
package com.power.spel;

import org.springframework.expression.AccessException;
import org.springframework.expression.BeanResolver;
import org.springframework.expression.EvaluationContext;

/**
* @author power
* @date 2018/10/9 下午9:09
*/
public class MyBeanResolver implements BeanResolver {
@Override
public Object resolve(EvaluationContext context, String beanName) throws AccessException {
if (beanName.equals("foo") || beanName.equals("bar")) {
return "MyBeanResolver";
}
if (beanName.equals("&foo")) {
return "MyBeanResolver-&foo";
}
throw new AccessException("not heard of " + beanName);
}
}
阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐