本文共 3623 字,大约阅读时间需要 12 分钟。
五、Velocity的历史简介
Velocity,Apache软件基金会的一个项目,是一个用Java写的模板引擎,用于将模板和从Java对象中获取的数据进行混合生成各种文字类型的文件。
Velocity经常在当下流行的MVC模式中被用来渲染视图,或者在XML文件中作为XSLT的替代品进行数据转换。
Velocity拥有自己的语言,也就是Velocity Template Language(VLT),它是生成简单易读模板的关键。使用VLT,我们可以简单且直观地定义变量,控制流程和迭代,以及访问Java对象中包含的信息。
下面是一段Velocity模板片段:
#foreach($field in $fields)
/**
* Returns the ${field.simpleName} property descriptor.
*
* @return the property descriptor
*/
public PropertyDescriptor ${field.simpleName}PropertyDescriptor() {
PropertyDescriptor theDescriptor = null;
return theDescriptor;
}
#end
#foreach($method in $methods)
/**
* Returns the ${method.simpleName}() method descriptor.
*
* @return the method descriptor
*/
public MethodDescriptor ${method.simpleName}MethodDescriptor() {
MethodDescriptor descriptor = null;
return descriptor;
}
#end
六、Velocity生成器使用方法
现在我们决定使用Velocity来升级我们的生成器,我们需要按照下面的步骤进行重新设计:
写一个用来生成代码的模板。
注解处理器从每一轮的environment中读取被注解的元素并将它们保存到容易访问的Java对象中——包括一个保存field的map对象,一个保存method的map对象,类名和包名等等。
注解处理器实例化Velocity的context。
注解处理器加载Velocity的模板。
注解处理器创建源文件(通过使用Filer),并且连同Velocity Context将一个写入器(writer)传递给Velocity的模板。
Velocity引擎生成源代码。
通过使用这种方法,你会发现处理器/生成器的代码非常清晰,结构良好,并且易于理解和维护。
下面让我们一步一步来实现:
步骤1:写模板
为了简单起见,我们不会列出完整的BeanInfo生成器代码,只是列出部分与注解处理器一块编译时需要的field(成员变量)和method(方法)。
接下来让我们创建一个名为beaninfo.vm的(模板)文件,并把它放到包含注解处理器的Maven artifact项目的src/main/resources目录下。模板内容的示例如下:
package ${packageName};
import java.beans.MethodDescriptor;
import java.beans.ParameterDescriptor;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
public class ${className}BeanInfo
extends java.beans.SimpleBeanInfo {
/**
* Gets the bean class object.
*
* @return the bean class
*/
public static Class getBeanClass() {
return ${packageName}.${className}.class;
}
/**
* Gets the bean class name.
*
* @return the bean class name
*/
public static String getBeanClassName() {
return "${packageName}.${className}";
}
/**
* Finds the right method by comparing name & number of parameters in the class
* method list.
*
* @param classObject the class object
* @param methodName the method name
* @param parameterCount the number of parameters
*
* @return the method if found, <code>null</code> otherwise
*/
public static Method findMethod(Class classObject, String methodName, int parameterCount) {
try {
// since this method attempts to find a method by getting all
// methods from the class, this method should only be called if
// getMethod cannot find the method
Method[] methods = classObject.getMethods();
for (Method method : methods) {
if (method.getParameterTypes().length == parameterCount
&& method.getName().equals(methodName)) {
return method;
}
}
} catch (Throwable t) {
return null;
}
return null;
}
#foreach($field in $fields)
/**
* Returns the ${field.simpleName} property descriptor.
*
* @return the property descriptor
*/
public PropertyDescriptor ${field.simpleName}PropertyDescriptor() {
PropertyDescriptor theDescriptor = null;
return theDescriptor;
}
#end
#foreach($method in $methods)
/**
* Returns the ${method.simpleName}() method descriptor.
*
* @return the method descriptor
*/
public MethodDescriptor ${method.simpleName}MethodDescriptor() {
MethodDescriptor descriptor = null;
Method method = null;
try {
// finds the method using getMethod with parameter types
// TODO parameterize parameter types
Class[] parameterTypes = {java.beans.PropertyChangeListener.class};
method = getBeanClass().getMethod("${method.simpleName}", parameterTypes);
} catch (Throwable t) {
// alternative: use findMethod
// TODO parameterize number of parameters
method = findMethod(getBeanClass(), "${method.simpleName}", 1);
}
try {
本教程由尚硅谷教育大数据研究院出品,如需转载请注明来源。