JSP最终生成为
.java类,这些类被编译为Servlet。检查服务器的工作文件夹。对于Tomcat,
/test.jsp将
/org/apache/jsp/test_jsp.java在Tomcat的
/work文件夹中生成一个文件。
以下几行
<jsp:useBean id="dog" scope="application"> <jsp:setProperty name="dog" property="breed" value="House Dog !!!"/></jsp:useBean>
(我所做的唯一更改是添加了一个程序包;无程序包类是Bad™)
生成为
com.example.Dog dog = null; synchronized (application) { dog = (com.example.Dog) _jspx_page_context.getAttribute("dog", javax.servlet.jsp.PageContext.APPLICATION_SCOPE); if (dog == null){ dog = new com.example.Dog(); _jspx_page_context.setAttribute("dog", dog, javax.servlet.jsp.PageContext.APPLICATION_SCOPE); out.write("n"); out.write(" "); org.apache.jasper.runtime.JspRuntimeLibrary.introspecthelper(_jspx_page_context.findAttribute("dog"), "breed", "House Dog !!!", null, null, false); out.write('n'); } }Tomcat是开源的,根据其源代码,
JspRuntimeLibrary#introspecthelper()方法委托
internalIntrospecthelper()最终实现此目的:
Method method = null;Class<?> type = null;Class<?> propertyEditorClass = null;try { java.beans.BeanInfo info = java.beans.Introspector.getBeanInfo(bean.getClass()); if ( info != null ) { java.beans.PropertyDescriptor pd[] = info.getPropertyDescriptors(); for (int i = 0 ; i < pd.length ; i++) { if ( pd[i].getName().equals(prop) ) { method = pd[i].getWriteMethod(); type = pd[i].getPropertyType(); propertyEditorClass = pd[i].getPropertyEditorClass(); break; } } } if ( method != null ) { if (type.isArray()) { if (request == null) { throw new JasperException( Localizer.getMessage("jsp.error.beans.setproperty.noindexset")); } Class<?> t = type.getComponentType(); String[] values = request.getParameterValues(param); //XXX Please check. if(values == null) return; if(t.equals(String.class)) { method.invoke(bean, new Object[] { values }); } else { createTypedArray (prop, bean, method, values, t, propertyEditorClass); } } else { if(value == null || (param != null && value.equals(""))) return; Object oval = convert(prop, value, type, propertyEditorClass); if ( oval != null ) method.invoke(bean, new Object[] { oval }); } }} catch (Exception ex) { Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); ExceptionUtils.handleThrowable(thr); throw new JasperException(ex);}您会看到,它
java.beans.Introspector用于通过获取bean信息和属性
BeanInfo#getPropertyDescriptors()。所需的
<jsp:setProperty>方法如获得
java.lang.reflect.Method通过
PropertyDescriptor#getWriteMethod()。最后,它使用Reflection
API调用该方法。



