【问题标题】:Intercept field access of java objects in Rhino在 Rhino 中拦截 java 对象的字段访问
【发布时间】:2012-05-16 00:57:40
【问题描述】:

是否可以在执行的 JavaScript 代码中拦截 Java 对象的字段(和方法)访问?就像 JSCocoa 中允许处理属性和方法访问的委托一样。

【问题讨论】:

    标签: java javascript rhino


    【解决方案1】:

    您可以使用 Context.setWrapFactory 来指定如何包装 Java 对象。 这里显示了打印字段访问和方法调用的包装器:

    InterceptWrapFactory.java

    import org.mozilla.javascript.Context;
    import org.mozilla.javascript.Scriptable;
    import org.mozilla.javascript.WrapFactory;
    public class InterceptWrapFactory extends WrapFactory{
        @Override
        public Scriptable wrapAsJavaObject(Context cx, Scriptable scope,
                Object javaObject, Class<?> staticType) {
            return new InterceptNativeObject(scope, javaObject, staticType);
        }
    }
    

    InterceptNativeObject.java

    import org.mozilla.javascript.NativeJavaMethod;
    import org.mozilla.javascript.NativeJavaObject;
    import org.mozilla.javascript.Scriptable;
    public class InterceptNativeObject extends NativeJavaObject {
        @Override
        public Object get(String name, Scriptable start) {
            Object res = super.get(name, start);
            System.out.println("Field get name="+name+" result="+res);
            if (res instanceof NativeJavaMethod) {
                NativeJavaMethod method = (NativeJavaMethod) res;
                return new JavaMethodWrapper(method);
            }
            return res;
        }
        public InterceptNativeObject(Scriptable scope, Object javaObject,
                Class<?> staticType) {
            super(scope, javaObject, staticType);
        }
    }
    

    JavaMethodWrapper.java

    import org.mozilla.javascript.Context;
    import org.mozilla.javascript.Function;
    import org.mozilla.javascript.NativeJavaMethod;
    import org.mozilla.javascript.Scriptable;
    
    public class JavaMethodWrapper implements Function {
        NativeJavaMethod method;
        public JavaMethodWrapper(NativeJavaMethod method) {
            this.method = method;
        }
        public boolean hasInstance(Scriptable instance) {
            return method.hasInstance(instance);
        }
        public Object call(Context cx, Scriptable scope, Scriptable thisObj,
                Object[] args) {
            System.out.println("Call method: "+method);
            return method.call(cx, scope, thisObj, args);
        }
        public boolean has(int index, Scriptable start) {
            return method.has(index, start);
        }
        public Scriptable construct(Context cx, Scriptable scope, Object[] args) {
            return method.construct(cx, scope, args);
        }
        public void put(int index, Scriptable start, Object value) {
            method.put(index, start, value);
        }
        public void delete(int index) {
            method.delete(index);
        }
        public Scriptable createObject(Context cx, Scriptable scope) {
            return method.createObject(cx, scope);
        }
        public boolean has(String name, Scriptable start) {
            return method.has(name, start);
        }
        public void defineConst(String name, Scriptable start) {
            method.defineConst(name, start);
        }
        public void put(String name, Scriptable start, Object value) {
            method.put(name, start, value);
        }
        public void delete(String name) {
            method.delete(name);
        }
        public Scriptable getPrototype() {
            return method.getPrototype();
        }
        public void setPrototype(Scriptable m) {
            method.setPrototype(m);
        }
        public Scriptable getParentScope() {
            return method.getParentScope();
        }
        public void setParentScope(Scriptable m) {
            method.setParentScope(m);
        }
        public Object[] getIds() {
            return method.getIds();
        }
        public Object get(int index, Scriptable start) {
            return method.get(index, start);
        }
        public Object get(String name, Scriptable start) {
            return method.get(name, start);
        }
        public String getClassName() {
            return method.getClassName();
        }
        public Object getDefaultValue(Class<?> typeHint) {
            return method.getDefaultValue(typeHint);
        }
    }
    

    这是一个测试代码:

    import java.util.Vector;
    
    import org.mozilla.javascript.Context;
    import org.mozilla.javascript.Scriptable;
    import org.mozilla.javascript.ScriptableObject;
    
    
    public class InterceptTest {
        public static void main(String[] args) {
            Context cx=Context.enter();
            cx.setWrapFactory(new InterceptWrapFactory());
            Scriptable root=cx.initStandardObjects();
            ScriptableObject.putProperty(root,"v", new Vector<String>());
            cx.evaluateString(root, "v.add('foo'); v.get(0)", "src", 1, null);
        }
    }
    

    【讨论】:

    • 非常感谢,这正是我想要的。我很好奇,您在哪里找到有关该主题的信息?
    【解决方案2】:

    作为 hog1e3 建议的替代方案,还可以实现 Scriptable 接口来拦截对类的方法/字段的调用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-30
      • 1970-01-01
      • 2016-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多