Tapestry灵魂——字节码生成

<script type="text/javascript"> document.location.href="http://blog.csdn.net/mindhawk/archive/2006/12/16/1445012.aspx"; </script>

    Tapestry最大的的一个特点就是通过字节码生成在运行时动态的创建页面的实例。这也是整个框架能有如此活力的基础。通过运行时的代码生成不仅使说明(specification),模板(template)和类结合起来形成一个统一的整体,更主要的是使程序员得到了极大的解放。所有重复性的,易出错的烦琐工作都有框架负责,动态的将必须的信息赋给页面。程序员需要的仅仅是关心一些最为基本的设置。

    Tapestry4对这个生成的过程作了一个较大的调整。和其它改进类似,页面生成也是通过HiveMind来组织的。将各种不同的生成策略使用接口分离开,然后再通过HiveMind的服务和配置组织在一起。

    与代码生成有关的主要对象大致可以分为三类。第一个是工厂方法,负责共的生成调度缓存的工作。另一类是基本生成工作类(enhance),负责各种不同的类型的代码生成工作。最后一个是对基本生成工作类的一个扩展,主要用于生成注入属性的字节码。至于如何实际生成字节码可以参见javassist

    工厂方法(ComponentConstructorFactory):整个项目只有一个实例,主要是提供一个统一的服务接口。
    基本生成类(EnhancementWorker):通过HiveMind组成成了一个责任链的形式(四人帮的 chain 模式),生成时会逐个调用各个实现类生成具体字节码。
    注入扩展类(InjectEnhancementWorker):这个扩展由一个基本生成类调用。由key/value的形式保存组织,用户可以根据自己的需要添加实现。key是该扩展的名称,value是具体的实现类。

Enhance

    上图没有列出所有的实现类。EnhancementWorker接口的主要实现有十多类,分别负责资源信息(InjectMessagesWorker)、说明(InjectSpecificationWorker)、定义属性(SpecifiedPropertyWorker)、参数(ParameterPropertyWorker)、注入分配(DispatchToInjectWorker)、组件(InjectComponentWorker)、Bean(InjectBeanWorker)、Asset(InjectAssetWorker)、抽象属性(AbstractPropertyWorker)、页面的接口(pageBeginRender等五类接口,InjectPageDetachListenerWorker,InjectPageAttachListenerWorker,InjectPageValidateListenerWorker,InjectPageBeginRenderListenerWorker,InjectPageEndRenderListenerWorker)等的生成工作。这十多个类的组成一个有序的 chain,抽象属性是这个序列的分水岭。大体顺序与我上面提到的一致,在抽象属性前的为一个集合,每一个都必须在抽象属性之前,但是他们之间没有顺序的限定。抽象属性之后的是一个集合。AnnotationEnhancementWorker 比较特殊,只有在java5以上才有效,它实际上是其它EnhancementWorker的一个调度。如果存在它会排在这个 chain 的最前面。

    注入分配(DispatchToInjectWorker)有它自己另外一套的配置,主要用户便于用户扩展注入的属性。框架提供的主要有六类。InjectMetaWorker,InjectObjectWorker,InjectPageWorker,InjectScriptWorker,InjectStateFlagWorker,InjectStateWorker。

以下是我编写的一个简单的组件,包含了其中所有的典型的生成字节码,并注明了是由谁生成的(因为考虑到复用,有些属性由第一个生成该属性的生成类完成):

public   class  $Enhance_21  extends  com.kft.tapestry.components.Enhance  {

    
/** InjectMessagesWorker */
    
private org.apache.tapestry.services.ComponentMessagesSource _$componentMessagesSource;

    
private org.apache.hivemind.Messages _$messages;

    
/** InjectSpecificationWorker */
    
private org.apache.tapestry.spec.IComponentSpecification _$specification;

    
/** SpecifiedPropertyWorker */
    
private java.lang.String _$sessionProperty;

    
private java.lang.String _$sessionProperty$default;

    
private java.lang.String _$specifiedProperty;

    
private java.lang.String _$specifiedProperty$default;

    
/** ParameterPropertyWorker */
    
private java.lang.String _$parameter;

    
private java.lang.String _$parameter$Default;

    
private boolean _$parameter$Cached;

    
private java.lang.Class _class$java$lang$String;

    
/** DispatchToInjectWorker & InjectMetaWorker */
    
private org.apache.tapestry.services.ComponentPropertySource _$componentPropertySource;

    
private org.apache.tapestry.coerce.ValueConverter _$valueConverter;

    
/** DispatchToInjectWorker & InjectObjectWorker */
    
private org.apache.tapestry.engine.IEngineService _$injectObject;

    
/** DispatchToInjectWorker & InjectScriptWorker */
    
private org.apache.tapestry.enhance.DeferredScript _$script;

    
/** DispatchToInjectWorker & InjectStateWorker */
    
private java.lang.Object _$injectState;

    
/** DispatchToInjectWorker & (InjectStateWorker or InjectStateFlagWorker) */
    
private org.apache.tapestry.engine.state.ApplicationStateManager _$applicationStateManager;

    
/** InjectComponentWorker */
    
private java.lang.Class _class$org$apache$tapestry$components$Insert;

    
private org.apache.hivemind.Location _$injectComponent$location;

    
private org.apache.tapestry.components.Insert _$injectComponent;

    
/** AbstractPropertyWorker */
    
private java.lang.String _$abstractProperty;

    
private java.lang.String _$abstractProperty$defaultValue;

    
/** 构造函数,信息由多个相关EnhancementWorker提供 */
    
public $Enhance_21(org.apache.tapestry.services.ComponentMessagesSource $1,
            org.apache.tapestry.spec.IComponentSpecification $
2, java.lang.Class $3,
            org.apache.tapestry.services.ComponentPropertySource $
4,
            org.apache.tapestry.coerce.ValueConverter $
5,
            org.apache.tapestry.engine.IEngineService $
6,
            org.apache.tapestry.enhance.DeferredScript $
7,
            org.apache.tapestry.engine.state.ApplicationStateManager $
8, java.lang.Class $9,
            org.apache.hivemind.Location $
10{
        
// InjectMessagesWorker
        _$componentMessagesSource = $1;

        
// InjectSpecificationWorker
        _$specification = $2;

        
// ParameterPropertyWorker or other(公用属性只需生成一次,由最先生成的完成)
        _class$java$lang$String = $3;

        
// DispatchToInjectWorker & InjectMetaWorker
        _$componentPropertySource = $4;
        _$valueConverter 
= $5;

        
// DispatchToInjectWorker & InjectObjectWorker
        _$injectObject = $6;

        
// DispatchToInjectWorker & InjectScriptWorker
        _$script = $7;

        
// DispatchToInjectWorker & (InjectStateWorker or InjectStateFlagWorker)
        _$applicationStateManager = $8;

        
// InjectComponentWorker
        _class$org$apache$tapestry$components$Insert = $9;
        _$injectComponent$location 
= $10;
    }


    
/** ParameterPropertyWorker */
    
public void cleanupAfterRender(org.apache.tapestry.IRequestCycle $1{
        
super.cleanupAfterRender($1);
        org.apache.tapestry.IBinding parameterBinding 
= getBinding("parameter");
        
if (_$parameter$Cached && !parameterBinding.isInvariant()) {
            _$parameter$Cached 
= false;
            _$parameter 
= _$parameter$Default;
        }


    }


    
/** InjectComponentWorker */
    
public org.apache.tapestry.components.Insert getInjectComponent() {
        
return _$injectComponent;
    }


    
/** InjectSpecificationWorker */
    
public void setSpecifiedProperty(java.lang.String $1{
        _$specifiedProperty 
= $1;
    }


    
/** DispatchToInjectWorker & InjectStateFlagWorker */
    
public boolean isInjectStateFlag() {
        
return _$applicationStateManager.exists("visit");
    }


    
/** DispatchToInjectWorker & InjectPageWorker */
    
public org.apache.tapestry.IPage getInjectPage() {
        
return getPage().getRequestCycle().getPage("Home");
    }


    
/** InjectAssetWorker */
    
public org.apache.tapestry.IAsset getAsset() {
        
return getAsset("$template");
    }


    
/** InjectSpecificationWorker */
    
public org.apache.tapestry.spec.IComponentSpecification getSpecification() {
        
return _$specification;
    }


    
/** DispatchToInjectWorker & InjectMetaWorker */
    
public java.lang.String getInjectMeta() {
        java.lang.String meta 
= _$componentPropertySource.getComponentProperty(this"meta");
        
return (java.lang.String) _$valueConverter.coerceValue(meta, _class$java$lang$String);
    }


    
/** DispatchToInjectWorker & InjectObjectWorker */
    
public org.apache.tapestry.engine.IEngineService getInjectObject() {
        
return _$injectObject;
    }


    
/** InjectMessagesWorker */
    
public org.apache.hivemind.Messages getMessages() {
        
if (_$messages == null)
            _$messages 
= _$componentMessagesSource.getMessages(this);
        
return _$messages;
    }


    
/** AbstractPropertyWorker */
    
public void setAbstractProperty(java.lang.String $1{
        _$abstractProperty 
= $1;
    }


    
/** InjectBeanWorker */
    
public pojo.Bean getBean() {
        
return (pojo.Bean) getBeans().getBean("bean");
    }


    
/** SpecifiedPropertyWorker */
    
public java.lang.String getSpecifiedProperty() {
        
return _$specifiedProperty;
    }


    
/** ParameterPropertyWorker */
    
public java.lang.String getParameter() {
        
if (_$parameter$Cached)
            
return _$parameter;
        org.apache.tapestry.IBinding binding 
= getBinding("parameter");
        
if (binding == null)
            
return _$parameter$Default;
        java.lang.String result 
= (java.lang.String) binding.getObject(_class$java$lang$String);
        
if (isRendering() || binding.isInvariant()) {
            _$parameter 
= result;
            _$parameter$Cached 
= true;
        }

        
return result;
    }


    
/** DispatchToInjectWorker & InjectStateWorker */
    
public java.lang.Object getInjectState() {
        
if (_$injectState == null)
            _$injectState 
= (java.lang.Object) _$applicationStateManager.get("visit");
        
return _$injectState;
    }


    
/** AbstractPropertyWorker */
    
public java.lang.String getAbstractProperty() {
        
return _$abstractProperty;
    }


    
/** 页面读入初始化函数,信息由多个相关EnhancementWorker提供 */
    
public void finishLoad(org.apache.tapestry.IRequestCycle $1,
            org.apache.tapestry.engine.IPageLoader $
2,
            org.apache.tapestry.spec.IComponentSpecification $
3{
        
super.finishLoad($1, $2, $3);

        
// SpecifiedPropertyWorker
        _$sessionProperty$default = _$sessionProperty;
        _$specifiedProperty$
default = _$specifiedProperty;

        
// InjectComponentWorker
        _$injectComponent = (org.apache.tapestry.components.Insert) org.apache.tapestry.TapestryUtils
                .getComponent(
this"injectComponent",
                        _class$org$apache$tapestry$components$Insert, _$injectComponent$location);
        _$abstractProperty$defaultValue 
= _$abstractProperty;

        
// InjectPageDetachListenerWorker
        getPage().addPageDetachListener(this);

        
// InjectPageAttachListenerWorker
        getPage().addPageAttachListener(this);

        
// InjectPageValidateListenerWorker
        getPage().addPageValidateListener(this);

        
// InjectPageBeginRenderListenerWorker
        getPage().addPageBeginRenderListener(this);

        
// InjectPageEndRenderListenerWorker
        getPage().addPageEndRenderListener(this);
    }


    
/** DispatchToInjectWorker & InjectStateWorker */
    
public void setInjectState(java.lang.Object $1{
        _$applicationStateManager.store(
"visit", $1);
        _$injectState 
= $1;
    }


    
/** SpecifiedPropertyWorker */
    
public java.lang.String getSessionProperty() {
        
return _$sessionProperty;
    }


    
public void setSessionProperty(java.lang.String $1{
        org.apache.tapestry.Tapestry.fireObservedChange(
this"sessionProperty", $1);
        _$sessionProperty 
= $1;
    }


    
/** ParameterPropertyWorker */
    
public void setParameter(java.lang.String $1{
        
if (!isInActiveState()) {
            _$parameter$Default 
= $1;
            
return;
        }

        org.apache.tapestry.IBinding binding 
= getBinding("parameter");
        
if (binding == null)
            
throw new org.apache.hivemind.ApplicationRuntimeException(
                    
"Parameter 'parameter' is not bound and can not be updated.");
        binding.setObject($
1);
        
if (isRendering()) {
            _$parameter 
= $1;
            _$parameter$Cached 
= true;
        }

    }


    
/** 清空使用过的属性,信息由多个相关EnhancementWorker提供 */
    
public void pageDetached(org.apache.tapestry.event.PageEvent $1{
        
super.pageDetached($1);

        
// SpecifiedPropertyWorker
        _$sessionProperty = _$sessionProperty$default;
        _$specifiedProperty 
= _$specifiedProperty$default;

        
// DispatchToInjectWorker & InjectStateWorker
        _$injectState = null;

        
// AbstractPropertyWorker
        _$abstractProperty = _$abstractProperty$defaultValue;
    }


    
/** DispatchToInjectWorker & InjectScriptWorker */
    
public org.apache.tapestry.IScript getInjectScript() {
        
return _$script.getScript();
    }


}

下面是这个组件的java类:

package  com.kft.tapestry.components;

import  org.apache.tapestry.BaseComponent;
import  org.apache.tapestry.IAsset;
import  org.apache.tapestry.IPage;
import  org.apache.tapestry.IScript;
import  org.apache.tapestry.components.Insert;
import  org.apache.tapestry.engine.IEngineService;
import  org.apache.tapestry.engine.PageService;
import  org.apache.tapestry.event.PageAttachListener;
import  org.apache.tapestry.event.PageBeginRenderListener;
import  org.apache.tapestry.event.PageDetachListener;
import  org.apache.tapestry.event.PageEndRenderListener;
import  org.apache.tapestry.event.PageEvent;
import  org.apache.tapestry.event.PageValidateListener;

import  pojo.Bean;

public   abstract   class  Enhance  extends  BaseComponent  implements  PageBeginRenderListener,
        PageEndRenderListener, PageAttachListener, PageDetachListener, PageValidateListener 
{
    
public abstract String getAbstractProperty();

    
public abstract String getSpecifiedProperty();
    
    
public abstract String getSessionProperty();

    
public abstract String getParameter();

    
public abstract Insert getInjectComponent();

    
public abstract Bean getBean();

    
public abstract IAsset getAsset();

    
public abstract IPage getInjectPage();
    
    
public abstract String getInjectMeta();
    
    
public abstract IEngineService getInjectObject();
    
    
public abstract IScript getInjectScript();
    
    
public abstract Object getInjectState();
    
    
public abstract boolean isInjectStateFlag();

    
public void pageAttached(PageEvent event) {
        
    }


    
public void pageBeginRender(PageEvent event) {
        
    }


    
public void pageValidate(PageEvent event) {
        
    }


    
public void pageDetached(PageEvent event) {
        
    }

}

下面是该组件的说明文件:

<? xml version="1.0" ?>

<! DOCTYPE component-specification PUBLIC
  "-//Apache Software Foundation//Tapestry Specification 4.0//EN"
  "http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd"
>
< component-specification  class ="com.kft.tapestry.components.Enhance" >

    
< bean  name ="bean"  class ="pojo.Bean"  property ="bean" />
    
    
< property  name ="specifiedProperty" />
    
< property  name ="sessionProperty"  persist ="session" />
    
    
< parameter  name ="parameter" />

    
< component  id ="injectComponent"  type ="Insert"  property ="injectComponent" >
        
< binding  name ="value"  value ="literal:mindhawk" />
    
</ component >
    
    
< asset  name ="$template"  path ="context:WEB-INF/component/Enhance.html"  property ="asset" />
    
    
< inject  property ="injectPage"  type ="page"  object ="Home" />
    
    
< meta  key ="meta"  value ="meta" />
  
    
< inject  property ="injectMeta"  type ="meta"  object ="meta" />

    
< inject  property ="injectObject"  object ="engine-service:page" />
    
    
< inject  property ="injectScript"  type ="script"  object ="Enhance.script" />

    
< inject  property ="injectState"  type ="state"  object ="visit" />
    
    
< inject  property ="injectStateFlag"  type ="state-flag"  object ="visit" />

</ component-specification >

模版文件很简单,不会对生成的代码有影响,这里就不列出来了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值