metaclass.java

来自「Groovy动态语言 运行在JVM中的动态语言 可以方便的处理业务逻辑变化大的业」· Java 代码 · 共 183 行

JAVA
183
字号
/*
 * Copyright 2005 John G. Wilson
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package groovy.lang;

import java.lang.reflect.Method;
import java.util.List;
import java.util.logging.Logger;

import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.runtime.MetaClassHelper;

/**
 * Base class for meta class implementations. 
 * The meta class is used to invoke methods or to get 
 * fields/properties. For proper initialization of this class 
 * it is not enough to only call the constructor, the
 * initialize() must be called too. The invoke methods should
 * check that initialize() was called. Adding methods is
 * valid unless initilise method was called. Therefore 
 * addNewStaticMethod and addNewInstanceMethod should check that
 * that initilise awas not called before.
 * 
 * 
 * @author John Wilson
 *
 */

public abstract class MetaClass {
    protected static final Logger log = Logger.getLogger(MetaClass.class.getName());
    protected static boolean useReflection = false;
    public static final Object NO_METHOD_FOUND = new Object();
    protected final Class theClass;
    private boolean isGroovyObject;
    
    public static boolean isUseReflection() {
        return MetaClass.useReflection;
    }

    /**
     * Allows reflection to be enabled in situations where bytecode generation
     * of method invocations causes issues.
     *
     * @param useReflection
     */
    public static void setUseReflection(boolean useReflection) {
        MetaClass.useReflection = useReflection;
    }
    
    protected MetaClass(final Class theClass) {
        this.theClass = theClass;
        isGroovyObject = GroovyObject.class.isAssignableFrom(theClass);
    }
    
    public boolean isGroovyObject(){
        return isGroovyObject;
    }
    
    public Object invokeMissingMethod(Object instance, String methodName, Object[] arguments) {
        GroovyObject pogo = (GroovyObject) instance;
        return pogo.invokeMethod(methodName,arguments);
    }
    
    public Object invokeMethod(Object object, String methodName, Object arguments) {
        if (arguments == null) {
            return invokeMethod(object, methodName, MetaClassHelper.EMPTY_ARRAY);
        }
        if (arguments instanceof Tuple) {
            Tuple tuple = (Tuple) arguments;
            return invokeMethod(object, methodName, tuple.toArray());
        }
        if (arguments instanceof Object[]) {
            return invokeMethod(object, methodName, (Object[])arguments);
        }
        else {
            return invokeMethod(object, methodName, new Object[]{arguments});
        }
    }
    
    public Object invokeMethod(Class sender, Object receiver, String methodName, Object[] arguments, boolean isCallToSuper, boolean fromInsideClass){
        return invokeMethod(receiver,methodName,arguments);
    }
    
    public Object getProperty(Class sender, Object receiver, String messageName, boolean useSuper, boolean fromInsideClass) {
        return getProperty(receiver,messageName);
    }
    
    public void setProperty(Class sender, Object receiver, String messageName, Object messageValue, boolean useSuper, boolean fromInsideClass) {
        setProperty(receiver,messageName,messageValue);
    }
    
    public Object getAttribute(Class sender, Object receiver, String messageName, boolean useSuper) {
        return getAttribute(receiver,messageName);
    }
    
    public void setAttribute(Class sender, Object receiver, String messageName, Object messageValue, boolean useSuper, boolean fromInsideClass) {
        setAttribute(receiver,messageName,messageValue);
    }
    
    public abstract Object invokeConstructor(Object[] arguments);
    public abstract Object invokeMethod(Object object, String methodName, Object[] arguments);
    public abstract Object invokeStaticMethod(Object object, String methodName, Object[] arguments);
    public abstract Object getProperty(Object object, String property);
    public abstract void setProperty(Object object, String property, Object newValue);
    public abstract Object getAttribute(Object object, String attribute);
    public abstract void setAttribute(Object object, String attribute, Object newValue);
    /**
     * adds a new instance method to this meta class. Instance
     * methods are able to overwrite the original methods of the
     * class. Calling this method should not be done after 
     * initlise was called.
     * @param method the method to be added
     */
    public abstract void addNewInstanceMethod(Method method);
    /**
     * adds a new static method to this meta class. This is only
     * possible as long as initilise was not called.
     * @param method the method to be added
     */
    public abstract void addNewStaticMethod(Method method);
    /**
     * complete the initlialisation process. After this method
     * is called no methods should be added to the meta class.
     * Invocation of methods or access to fields/proeprties is
     * forbidden unless this method is called. This method 
     * should contain any initialisation code, taking a longer
     * time to complete. An example is the creation of the 
     * Reflector. It is suggested to synchronize this 
     * method.
     */
    public abstract void initialize();
    
    public abstract List getProperties();
    public abstract ClassNode getClassNode();
    public abstract List getMetaMethods();
    
    public abstract List getMethods();
    
    /**
     * Warning, this method will be removed
     * @deprecated use invokeConstructor instead
     */
    public Object invokeConstructorAt(Class at, Object[] arguments) {
        return invokeConstructor(arguments);
    }

    /**
     * Selects a method by name and argument classes. This method
     * does not search for an exact match, it searches for a compatible
     * method. For this the method selection mechanism is used as provided
     * bye the implementation of this MetaClass. pickMethod may or may
     * not used during the method selection process when invoking a method
     * thereis no warranty for that.
     * 
     * @returns a matching MetaMethod or null
     * @throws GroovyRuntimeException if there is more than one matching method
     */
    public abstract MetaMethod pickMethod(String methodName, Class[] arguments);
    
    /**
     * Warning, this method will be removed
     * @deprecated usw pickMethod instead
     */
    protected MetaMethod retrieveMethod(String methodName, Class[] arguments) {
        return pickMethod(methodName,arguments);
    }

}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?