论坛首页 Web前端技术论坛

Gwt延迟绑定介绍

浏览 8785 次
精华帖 (1) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-10-19  
GWT
Gwt延迟绑定介绍

Gwt的延迟绑定是一种gwt对反射机制的一种支持方案。简单的说就是在使用gwt进行代码开发的时候,可以使用接口和抽象类,而不用管它的实现,在编译后或者host模式的情况下,gwt会自己跟模块配置的信息来使用具体哪一个实现类替代代码中的接口和抽象类。

使用说明:

1. 定义接口或者抽象类,然后再定义一个实现类。

2. 在xxx.gwt.xml(模块文件中定义)替换的参数信息和具体替换的类
<replace-with class="com.google.gwt.user.client.impl.DOMImplMozilla">
		<when-type-is class="com.google.gwt.user.client.impl.DOMImpl"/>
		<when-property-is name="user.agent" value="gecko1_8"/>
	</replace-with>

上面的配置是将在firefox浏览器里面使用DOMImpl该类的地方使用DOMImplMozilla这个类进行替换。其中的replace-with是指实际用到的类,when-type-is则是要替换的类,when-property-is则是一些参数信息,可以添加0到多个。另外,关于参数的配置还可以加一些逻辑的限制,如Any,
<any>
      <when-property-is name="user.agent" value="gecko"/>
      <when-property-is name="user.agent" value="gecko1_8" />
    </any>


3. 在代码中使用
通过GWT.create方法可以动态的获取不同的实现类,如下:
DOMImpl impl = (DOMImpl) GWT.create(DOMImpl.class);
再结合gwt的dom模块的配置信息(如下),impl对象将会根据不同的浏览器而动态采用不同的domimpl类的实现。

<module>
	<inherits name="com.google.gwt.core.Core"/>
	<inherits name="com.google.gwt.user.UserAgent"/>

	<replace-with class="com.google.gwt.user.client.impl.DOMImplOpera">
		<when-type-is class="com.google.gwt.user.client.impl.DOMImpl"/>
		<when-property-is name="user.agent" value="opera"/>
	</replace-with>

	<replace-with class="com.google.gwt.user.client.impl.DOMImplSafari">
		<when-type-is class="com.google.gwt.user.client.impl.DOMImpl"/>
		<when-property-is name="user.agent" value="safari"/>
	</replace-with>

	<replace-with class="com.google.gwt.user.client.impl.DOMImplIE6">
		<when-type-is class="com.google.gwt.user.client.impl.DOMImpl"/>
		<when-property-is name="user.agent" value="ie6"/>
	</replace-with>

	<replace-with class="com.google.gwt.user.client.impl.DOMImplMozilla">
		<when-type-is class="com.google.gwt.user.client.impl.DOMImpl"/>
		<when-property-is name="user.agent" value="gecko1_8"/>
	</replace-with>

	<replace-with class="com.google.gwt.user.client.impl.DOMImplMozillaOld">
		<when-type-is class="com.google.gwt.user.client.impl.DOMImpl"/>
		<when-property-is name="user.agent" value="gecko"/>
	</replace-with>
</module>





参考:
http://code.google.com/docreader/#p=google-web-toolkit-doc-1-5&s=google-web-toolkit-doc-1-5&t=DevGuideDeferredBinding
   发表时间:2008-10-28  
最近正好项目用到延迟绑定,顺便帮楼主完善一下这篇文章“在代码中使用”的部分
延迟绑定很强大,反射,注解都可以支持
我用个实际例子来介绍:例如现在GWT中有很多Animal接口的实现类,比如Cat,Dog等等,现在需要在onModuleLoad的时候能够将Animal的所有实现类实例化,简单的写法就是一个一个地new,当实现类很多时候不仅累而且容易出错,这时候可以用延迟绑定来实现

首先在入口类里面写个空的类,然后用GWT.create方法来实例化它

private static class AnimalCreator{}

public void onModuleLoad(){
  GWT.create(AnimalCreator.class);
}


在配置XML文件里面做如下配置
<generate-with class="com.google.generator.AnimalGenerator">
  <when-type-assignable class="com.google.client.AnimalCreator"/>  
</generate-with>


解释一下这个配置:
当代码执行到GWT.create(AnimalCreator.class)时,GWT会调用AnimalGenerator这个类的generate方法(AnimalGenerator必须实现com.google.gwt.core.ext.Generator接口),generate方法返回一个类名的字符串(含package name),GWT.create方法将会根据这个字符串找到实际的类,然后将它实例化。
需要指出的是,上述过程都是在compile期间发生。也就是说这个Generator的实现类并不会被编译成js,所以不要把这个类放到client包下面;同时,这也意味着在这个Generator类里面,我们可以使用jdk提供的类,而不是局限于GWT JRE Emulation

下面直接给出AnimalGenerator的代码

public class ShowcaseGenerator extends Generator {
	private String className=null;
	private String packageName=null;
	
  public String generate(TreeLogger logger, GeneratorContext context,String typeName) throws UnableToCompleteException {
    try{
    	JClassType classType=context.getTypeOracle().getType(typeName);
    	//取包名
    	packageName=classType.getPackage().getName();
    	//取类名,然后加上Impl,也就是AnimalCreatorImpl
    	className=classType.getClass().getSimpleSourceName()+"Impl";
    	generateClass(logger,context);
  	}catch(Exception e){
  		logger.log(TreeLogger.ERROR, "ERROR!!!", e); 
  	}
  	return packageName+"."+className;
  }
  
  //尝试创建AnimalCreatorImpl这个类
  private void generateClass(TreeLogger logger, GeneratorContext context){
		PrintWriter printWriter = null;
		
		printWriter = context.tryCreate(logger, packageName, className);
		if (printWriter == null) return; 

		ClassSourceFileComposerFactory composer = null; 
		composer = new ClassSourceFileComposerFactory(packageName, className); 
		SourceWriter sourceWriter = null; 
		sourceWriter = composer.createSourceWriter(context, printWriter); 
		//手工写入代码 
		sourceWriter.println("public "+className+" {");
		sourceWriter.indent(); 
		try{
			JClassType superType=context.getTypeOracle().getType("com.google.client.Animal");
			JClassType[] Types=superType.getSubtypes();
			for(JClassType type:types){
				sourceWriter.println("new "+type.getPackage().getName()+"."+type.getName()+"();");
			}
		}catch(NotFoundException e){
			e.printStackTrace();	
		}
		sourceWriter.outdent(); 
		sourceWriter.println("}"); 		
		
		sourceWriter.outdent(); 
		sourceWriter.println("}"); 		
		//提交写入的新类
		context.commit(logger, printWriter); 
	}
}

generate方法返回的是com.google.client.AnimalCreatorImpl,但是我们目前并没有这个类,所以执行generateClass方法来动态生成这个类,在方法里面看到,我们首先找到com.google.client.Animal的所有实现类,然后将这些类名都以new Cat();这样的形式写入类的构造函数
那么当我们执行GWT.create(AnimalCreator.class)时,GWT会实例化我们用代码生成的AnimalCreatorImpl类,这个类的构造函数里面写着new Cat();new Dog();等等的代码,如果我们新建一个Animal接口的实现类,不用改动任何代码,这个类就会在onModuleLoad时被实例化
仔细查看GWT的com.google.gwt.core.ext包下面的API,我们可以发现更多对反射,注解等高级特性支持的方法
0 请登录后投票
   发表时间:2008-10-28  
edokeh 写道
最近正好项目用到延迟绑定,顺便帮楼主完善一下这篇文章“在代码中使用”的部分
延迟绑定很强大,反射,注解都可以支持
我用个实际例子来介绍:例如现在GWT中有很多Animal接口的实现类,比如Cat,Dog等等,现在需要在onModuleLoad的时候能够将Animal的所有实现类实例化,简单的写法就是一个一个地new,当实现类很多时候不仅累而且容易出错,这时候可以用延迟绑定来实现


非常感谢edokeh的完善。
0 请登录后投票
   发表时间:2008-11-18  
如果有个功能菜单,当点击后实例化该菜单对应的执行类,从而显示该菜单对应的界面...没有反射,这种功能如何实现?
0 请登录后投票
   发表时间:2008-11-18  
jvincent 写道
如果有个功能菜单,当点击后实例化该菜单对应的执行类,从而显示该菜单对应的界面...没有反射,这种功能如何实现?

实例化执行类这个步骤应当在点击之前就完成,然后将相应的对象与菜单项绑定,例如对于TreeItem类有个setUserObject的方法,可以用来进行绑定用户自定义对象
0 请登录后投票
   发表时间:2008-11-18  
执行类是保存在数据库中,在加载菜单的时候才取出...
这时怎么写xml文件?
0 请登录后投票
   发表时间:2008-11-18  
类名写在数据库里面?
0 请登录后投票
   发表时间:2008-11-18  
是啊...菜单可以手工增加,这样就必须在增加菜单的时候指定执行类,然后在加载的时候实例化...
0 请登录后投票
   发表时间:2008-11-18  
你是不是希望实现这样的需求:
1.点击菜单某项
2.发AJAX请求从服务器取得这个菜单项对应的UI类名
3.实例化UI类并显示

要是这样的话不如用iframe来显示对应的UI,菜单项控制iframe的src
要不这么做的话。。。我一时也没想到什么好办法。。。
0 请登录后投票
   发表时间:2008-11-18  
是的,只不过是在初始化的时候把当前登陆的用户的所有菜单都取出来,然后放到一个对象里,在点击菜单的时候就实例化对应的类...

要是支持反射就好了....
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics