metaclassimpl.java
来自「Groovy动态语言 运行在JVM中的动态语言 可以方便的处理业务逻辑变化大的业」· Java 代码 · 共 1,511 行 · 第 1/5 页
JAVA
1,511 行
// we may have already found one for this name
if (isGetter && mbp.getGetter()==null) {
mbp.setGetter(propertyMethod);
} else if (!isGetter && mbp.getSetter()==null) {
mbp.setSetter(propertyMethod);
}
mbp.setField(mfp);
mp = mbp;
}
propertyIndex.put(propName, mp);
}
private void applyPropertyDescriptors(PropertyDescriptor[] propertyDescriptors) {
Map propertyMap = (Map) classPropertyIndex.get(theClass);
// now iterate over the map of property descriptors and generate
// MetaBeanProperty objects
for(int i=0; i<propertyDescriptors.length; i++) {
PropertyDescriptor pd = propertyDescriptors[i];
// skip if the property type is unknown (this seems to be the case if the
// property descriptor is based on a setX() method that has two parameters,
// which is not a valid property)
if(pd.getPropertyType() == null)
continue;
// get the getter method
Method method = pd.getReadMethod();
MetaMethod getter;
if(method != null)
getter = findMethod(method);
else
getter = null;
// get the setter method
MetaMethod setter;
method = pd.getWriteMethod();
if(method != null)
setter = findMethod(method);
else
setter = null;
// now create the MetaProperty object
MetaBeanProperty mp = new MetaBeanProperty(pd.getName(), pd.getPropertyType(), getter, setter);
//keep field
MetaFieldProperty field = null;
MetaProperty old = (MetaProperty) propertyMap.get(pd.getName());
if (old!=null) {
if (old instanceof MetaBeanProperty) {
field = ((MetaBeanProperty) old).getField();
} else {
field = (MetaFieldProperty) old;
}
mp.setField(field);
}
// put it in the list
// this will overwrite a possible field property
propertyMap.put(pd.getName(), mp);
}
}
/**
* Sets the property value on an object
*/
public void setProperty(Class sender,Object object, String name, Object newValue, boolean useSuper, boolean fromInsideClass) {
checkInitalised();
//----------------------------------------------------------------------
// handling of static
//----------------------------------------------------------------------
boolean isStatic = theClass != Class.class && object instanceof Class;
if (isStatic && object != theClass) {
MetaClass mc = registry.getMetaClass((Class) object);
mc.getProperty(sender,object,name,useSuper,fromInsideClass);
return;
}
//----------------------------------------------------------------------
// Unwrap wrapped values fo now - the new MOP will handle them properly
//----------------------------------------------------------------------
if (newValue instanceof Wrapper) newValue = ((Wrapper)newValue).unwrap();
MetaMethod method = null;
Object[] arguments = null;
//----------------------------------------------------------------------
// setter
//----------------------------------------------------------------------
MetaProperty mp = getMetaProperty(sender,name,useSuper, isStatic);
MetaProperty field = null;
if (mp != null) {
if (mp instanceof MetaBeanProperty) {
MetaBeanProperty mbp = (MetaBeanProperty) mp;
method = mbp.getSetter();
if (method!=null) arguments = new Object[] { newValue };
field = mbp.getField();
} else {
field = mp;
}
}
// check for a category method named like a setter
if (!useSuper && !isStatic && GroovyCategorySupport.hasCategoryInAnyThread()) {
String getterName = "set"+MetaClassHelper.capitalize(name);
method = getCategoryMethodSetter(sender,getterName,false);
if (method!=null) arguments = new Object[] { newValue };
}
//----------------------------------------------------------------------
// listener method
//----------------------------------------------------------------------
boolean ambigousListener = false;
boolean usesProxy = false;
if (method==null) {
method = (MetaMethod) listeners.get(name);
ambigousListener = method == AMBIGOUS_LISTENER_METHOD;
if ( method != null &&
!ambigousListener &&
newValue instanceof Closure)
{
// lets create a dynamic proxy
Object proxy =
MetaClassHelper.createListenerProxy(method.getParameterTypes()[0], name, (Closure) newValue);
arguments = new Object[] { proxy };
newValue = proxy;
usesProxy = true;
} else {
method = null;
}
}
//----------------------------------------------------------------------
// field
//----------------------------------------------------------------------
if (method==null && field!=null) {
field.setProperty(object,newValue);
return;
}
//----------------------------------------------------------------------
// generic set method
//----------------------------------------------------------------------
// check for a generic get method provided through a category
if (method==null && !useSuper && !isStatic && GroovyCategorySupport.hasCategoryInAnyThread()) {
method = getCategoryMethodSetter(sender,"set",true);
if (method!=null) arguments = new Object[]{name,newValue};
}
// the generic method is valid, if available (!=null), if static or
// if it is not static and we do no static access
if (method==null && genericSetMethod != null && !(!genericSetMethod.isStatic() && isStatic)) {
arguments = new Object[]{ name, newValue };
method = genericSetMethod;
}
//----------------------------------------------------------------------
// executing the getter method
//----------------------------------------------------------------------
if (method!=null) {
if (arguments.length==1) {
newValue = DefaultTypeTransformation.castToType(
newValue,
method.getParameterTypes()[0]);
arguments[0] = newValue;
} else {
newValue = DefaultTypeTransformation.castToType(
newValue,
method.getParameterTypes()[1]);
arguments[1] = newValue;
}
MetaClassHelper.doMethodInvoke(object,method,arguments);
return;
}
//----------------------------------------------------------------------
// error due to missing method/field
//----------------------------------------------------------------------
if (ambigousListener){
throw new GroovyRuntimeException("There are multiple listeners for the property "+name+". Please do not use the bean short form to access this listener.");
}
throw new MissingPropertyException(name, theClass);
}
private MetaProperty getMetaProperty(Class clazz, String name, boolean useSuper, boolean useStatic) {
Map propertyMap;
if (useStatic) {
propertyMap = staticPropertyIndex;
} else if (useSuper){
propertyMap = (Map) classPropertyIndexForSuper.get(clazz);
} else {
propertyMap = (Map) classPropertyIndex.get(clazz);
}
if (propertyMap==null) {
if (clazz!=theClass) {
return getMetaProperty(theClass,name,useSuper, useStatic);
} else {
return null;
}
}
return (MetaProperty) propertyMap.get(name);
}
/**
* Looks up the given attribute (field) on the given object
*/
public Object getAttribute(Class sender, Object object, String attribute, boolean useSuper, boolean fromInsideClass) {
checkInitalised();
boolean isStatic = theClass != Class.class && object instanceof Class;
if (isStatic && object != theClass) {
MetaClass mc = registry.getMetaClass((Class) object);
return mc.getAttribute(sender,object,attribute,useSuper);
}
MetaProperty mp = getMetaProperty(sender,attribute,useSuper, isStatic);
if (mp != null) {
if (mp instanceof MetaBeanProperty) {
MetaBeanProperty mbp = (MetaBeanProperty) mp;
mp = mbp.getField();
}
try {
// delegate the get operation to the metaproperty
if (mp != null) return mp.getProperty(object);
} catch(Exception e) {
throw new GroovyRuntimeException("Cannot read field: " + attribute,e);
}
}
throw new MissingFieldException(attribute, theClass);
}
/**
* Sets the given attribute (field) on the given object
*/
public void setAttribute(Class sender, Object object, String attribute, Object newValue, boolean useSuper, boolean fromInsideClass) {
checkInitalised();
boolean isStatic = theClass != Class.class && object instanceof Class;
if (isStatic && object != theClass) {
MetaClass mc = registry.getMetaClass((Class) object);
mc.setAttribute(sender,object,attribute,newValue,useSuper,fromInsideClass);
return;
}
MetaProperty mp = getMetaProperty(sender,attribute,useSuper, isStatic);
if (mp != null) {
if (mp instanceof MetaBeanProperty) {
MetaBeanProperty mbp = (MetaBeanProperty) mp;
mp = mbp.getField();
}
if (mp != null) {
mp.setProperty(object,newValue);
return;
}
}
throw new MissingFieldException(attribute, theClass);
}
public ClassNode getClassNode() {
if (classNode == null && GroovyObject.class.isAssignableFrom(theClass)) {
// lets try load it from the classpath
String className = theClass.getName();
String groovyFile = className;
int idx = groovyFile.indexOf('$');
if (idx > 0) {
groovyFile = groovyFile.substring(0, idx);
}
groovyFile = groovyFile.replace('.', '/') + ".groovy";
//System.out.println("Attempting to load: " + groovyFile);
URL url = theClass.getClassLoader().getResource(groovyFile);
if (url == null) {
url = Thread.currentThread().getContextClassLoader().getResource(groovyFile);
}
if (url != null) {
try {
/**
* todo there is no CompileUnit in scope so class name
* checking won't work but that mostly affects the bytecode
* generation rather than viewing the AST
*/
CompilationUnit.ClassgenCallback search = new CompilationUnit.ClassgenCallback() {
public void call( ClassVisitor writer, ClassNode node ) {
if( node.getName().equals(theClass.getName()) ) {
MetaClassImpl.this.classNode = node;
}
}
};
final ClassLoader parent = theClass.getClassLoader();
GroovyClassLoader gcl = (GroovyClassLoader) AccessContr
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?