Velocity源码分析(二)——渲染执行之Introspection
import java.beans.BeanInfo; import java.beans.Introspector; import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; public class SimpleBean{ private final String name = "SimpleBean"; private int size; public String getName(){ return this.name; } public int getSize(){ return this.size; } public void setSize( int size ) { this.size = size; } public static void main( String[] args ) throws IntrospectionException { BeanInfo info = Introspector.getBeanInfo( SimpleBean.class ); for ( PropertyDescriptor pd : info.getPropertyDescriptors() ) System.out.println( pd.getName() ); } }
- getIterator():支持迭代#foreache
- getMethod():支持方法调用
- getPropertyGet():支持获取属性值
- getPropertySet():支持设置属性值
public Object execute(Object o, InternalContextAdapter context) throws MethodInvocationException {
if (referenceType == RUNT)
return null;
Object result = getVariableValue(context, rootString);
if (result == null && !strictRef)
{
return EventHandlerUtil.invalidGetMethod(rsvc, context,
"$" + rootString, null, null, uberInfo);
}
try
{
Object previousResult = result;
int failedChild = -1;
for (int i = 0; i < numChildren; i++)
{
if (strictRef && result == null)
{
String name = jjtGetChild(i).getFirstToken().image;
throw new VelocityException("Attempted to access '"
+ name + "' on a null value at "
+ Log.formatFileString(uberInfo.getTemplateName(),
+ jjtGetChild(i).getLine(), jjtGetChild(i).getColumn()));
}
previousResult = result;
//遍历执行子节点的execute方法
result = jjtGetChild(i).execute(result,context);
if (result == null && !strictRef) // If strict and null then well catch this
// next time through the loop
{
failedChild = i;
break;
}
}
/**
......
*/
}
public Object execute(Object o, InternalContextAdapter context) throws MethodInvocationException { if (o instanceof NullInstance && ((NullInstance) o).isNotNull()) { return o; }
/*
* 获取方法信息
*/
VelMethod method = null;
Object [] params = new Object[paramCount];
try
{
// 计算参数类型
final Class[] paramClasses = paramCount > 0 ? new Class[paramCount] : ArrayUtils.EMPTY_CLASS_ARRAY;
for (int j = 0; j < paramCount; j++)
{
params[j] = jjtGetChild(j + 1).value(context);
if (params[j] != null)
{
paramClasses[j] = params[j].getClass();
}
}
//从cache中获取Method信息
MethodCacheKey mck = new MethodCacheKey(methodName, paramClasses);
IntrospectionCacheData icd = context.icacheGet( mck );
if ( icd != null && (o != null && icd.contextData == o.getClass()) )
{
method = (VelMethod) icd.thingy;
}
else
{
//缓存未命中,调用UberIntrospectImpl.getMethod()执行自省
method = rsvc.getUberspect().getMethod(o, methodName, params, new Info(getTemplateName(), getLine(), getColumn()));
if ((method != null) && (o != null))
{
icd = new IntrospectionCacheData();
icd.contextData = o.getClass();
icd.thingy = method;
//更新缓存
context.icachePut( mck, icd );
}
}
if (typeOptimum && method instanceof VelMethodImpl) {
this.recordedData = icd;
}
/*
* ....
*/
}
public VelMethod getMethod(Object obj, String methodName, Object[] args, Info i) throws Exception { if (obj == null) { return null; } //调用Inspector.getMethod() Method m = introspector.getMethod(obj.getClass(), methodName, args); if (m != null) {
//封装VelMethodImpl return new VelMethodImpl(m); }
Class cls = obj.getClass();
// if it's an array
if (cls.isArray())
{
// check for support via our array->list wrapper
m = introspector.getMethod(ArrayListWrapper.class, methodName, args);
if (m != null)
{
// and create a method that knows to wrap the value
// before invoking the method
return new VelMethodImpl(m, true);
}
}
// watch for classes, to allow calling their static methods (VELOCITY-102)
else if (cls == Class.class)
{
m = introspector.getMethod((Class)obj, methodName, args);
if (m != null)
{
return new VelMethodImpl(m);
}
}
return null;
}
public Method getMethod(final Class c, final String name, final Object[] params) throws IllegalArgumentException { try { //调用父类IntrospectorBase.getMethod()方法 return super.getMethod(c, name, params); } catch(MethodMap.AmbiguousException ae) { /*异常处理*/ }
return null;
}
public Method getMethod(final Class c, final String name, final Object[] params) throws IllegalArgumentException,MethodMap.AmbiguousException { if (c == null) { throw new IllegalArgumentException ("class object is null!"); } if (params == null) { throw new IllegalArgumentException("params object is null!"); }
IntrospectorCache ic = getIntrospectorCache();
ClassMap classMap = ic.get(c);
if (classMap == null)
{
classMap = ic.put(c);
}
return classMap.findMethod(name, params);
}
public ClassMap put(final Class c) { //构造ClassMap final ClassMap classMap = new ClassMap(c, log); synchronized (classMapCache) { classMapCache.put(c, classMap); classNameCache.add(c.getName()); } return classMap; }
public ClassMap(final Class clazz, final Log log) { this.clazz = clazz; this.log = log;
if (debugReflection && log.isDebugEnabled())
{
log.debug("=================================================================");
log.debug("== Class: " + clazz);
}
methodCache = createMethodCache();
if (debugReflection && log.isDebugEnabled())
{
log.debug("=================================================================");
}
}
private MethodCache createMethodCache() { MethodCache methodCache = new MethodCache(log); for (Class classToReflect = getCachedClass(); classToReflect != null ; classToReflect = classToReflect.getSuperclass()) { if (Modifier.isPublic(classToReflect.getModifiers())) { populateMethodCacheWith(methodCache, classToReflect); } Class [] interfaces = classToReflect.getInterfaces(); for (int i = 0; i < interfaces.length; i++) { populateMethodCacheWithInterface(methodCache, interfaces[i]); } } // return the already initialized cache return methodCache; }
public VelPropertyGet getPropertyGet(Object obj, String identifier, Info i) throws Exception { if (obj == null) { return null; }
Class claz = obj.getClass();
// 构造get"属性名"()形式的Executor
AbstractExecutor executor = new PropertyExecutor(log, introspector, claz, identifier);
//构造一个Map形式的Executor
if (!executor.isAlive())
{
executor = new MapGetExecutor(log, claz, identifier);
}
// 构造get("属性名")形式的Executor
if (!executor.isAlive())
{
executor = new GetExecutor(log, introspector, claz, identifier);
}
//构建is"属性名"形式的executor
if (!executor.isAlive())
{
executor = new BooleanPropertyExecutor(log, introspector, claz,
identifier);
}
return (executor.isAlive()) ? new VelGetterImpl(executor) : null;
}
blog comments powered by Disqus