With语法模型
使用动态模型可以自定义语法类的模型,比如这里将要讲述了With语法模型。
1.资源自动关闭
在Java中资源使用完毕后是需要手工释放的,比如InputStream、OutputStream和Connection等,那么是否可以实现资源的自动关闭和释放呢?为此目标我们可以创建With语法模型。
2.With语法模型
2.1.原理
With语法模型,使用Java示意代码如下。
//创建各种资源
Object resource1 = ...;
Object resource2 = ...;
...
Object resourcen = ...;
try{
//使用资源,执行一些动作
doSomeThing();
}finally{
//释放资源,按照创建的相反顺序
resourcen.close();
...
resource2.close();
resource1.close();
}
2.2.定义With语法模型
主要见Resources和Do两个子节点,Resources是创建资源的动作列表,Do是资源创建后要执行的动作列表。
<?xml version="1.0" encoding="utf-8"?>
<thing name="With" descriptors="xworker.lang.MetaDescriptor3" extends="xworker.lang.actions.SelfAction">
<actions>
<JavaAction name="run" outerClassName="xworker.lang.actions.With" methodName="run"></JavaAction>
</actions>
<attribute name="name"></attribute>
<attribute name="label"></attribute>
<attribute name="description" inputtype="html"></attribute>
<thing name="Resources" extends="xworker.lang.actions.Actions"></thing>
<thing name="Do" extends="xworker.lang.actions.Actions"></thing>
</thing>
2.3.With语法模型的实现
public class With {
public static Object run(ActionContext actionContext) {
Thing self = actionContext.getObject("self");
List<Object> resList = new ArrayList<Object>();
try {
Bindings bindings = actionContext.peek();
bindings.setVarScopeFlag();
for(Thing resources : self.getChilds("Resources")) {
for(Thing resource : resources.getChilds()) {
Object res = resource.getAction().run(actionContext);
resList.add(res);
bindings.put(resource.getMetadata().getName(), res);
}
}
Thing doac = self.getThing("Do@0");
if(doac != null) {
return UtilAction.runChildActions(doac.getChilds(), actionContext);
}else {
return null;
}
}finally {
for(int i=resList.size() -1 ; i >= 0; i--) {
Object res = resList.get(i);
try {
close(res, actionContext);
}catch(Exception e) {
}
}
}
}
public static void close(Object obj, ActionContext actionContext) throws IOException, SQLException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
if(obj == null) {
return;
}
if(obj instanceof InputStream) {
((InputStream) obj).close();
}else if(obj instanceof OutputStream) {
((OutputStream) obj).close();
}else if(obj instanceof Connection) {
((Connection) obj).close();
}else if(obj instanceof ActionContainer){
((ActionContainer) obj).doAction("close", actionContext);
}else if(obj instanceof Thing){
((Thing) obj).doAction("close", actionContext);
}else {
Method closeMethod = obj.getClass().getDeclaredMethod("close", new Class<?>[0]);
if(closeMethod != null) {
closeMethod.invoke(obj, new Object[0]);
}
}
}
}
3.使用With模型
下面是使用With模型的例子,创建一个FileInputStram,使用readLine按行读取并打印到控制台。
<?xml version="1.0" encoding="utf-8"?>
<With descriptors="xworker.lang.actions.Actions/@With">
<Resources>
<FileInputStream name="fileInputStream" descriptors="xworker.io.InputStreamActions/@FileInputStream"
file="xworker:webroot/index.html"></FileInputStream>
</Resources>
<Do>
<readLine descriptors="xworker.io.ReaderActions/@readLine" reader="var:fileInputStream"
loop="true">
<actions>
<Println name="onRead" _xmeta_id_="Println" varName="var:line"></Println>
</actions>
</readLine>
</Do>
</With>