Gwt的延迟绑定是一种gwt对反射机制的一种支持方案。简单的说就是在使用gwt进行代码开发的时候,可以使用接口和抽象类,而不用管它的实现,在编译后或者host模式的情况下,gwt会自己跟模块配置的信息来使用具体哪一个实现类替代代码中的接口和抽象类。
使用说明:
1. 定义接口或者抽象类,然后再定义一个实现类。
2. 在xxx.gwt.xml(模块文件中定义)替换的参数信息和具体替换的类
上面的配置是将在firefox浏览器里面使用DOMImpl该类的地方使用DOMImplMozilla这个类进行替换。其中的replace-with是指实际用到的类,when-type-is则是要替换的类,when-property-is则是一些参数信息,可以添加0到多个。另外,关于参数的配置还可以加一些逻辑的限制,如Any,
3. 在代码中使用
通过GWT.create方法可以动态的获取不同的实现类,如下:
DOMImpl impl = (DOMImpl) GWT.create(DOMImpl.class);
再结合gwt的dom模块的配置信息(如下),impl对象将会根据不同的浏览器而动态采用不同的domimpl类的实现。
延迟绑定很强大,反射,注解都可以支持
我用个实际例子来介绍:例如现在GWT中有很多Animal接口的实现类,比如Cat,Dog等等,现在需要在onModuleLoad的时候能够将Animal的所有实现类实例化,简单的写法就是一个一个地new,当实现类很多时候不仅累而且容易出错,这时候可以用延迟绑定来实现
首先在入口类里面写个空的类,然后用GWT.create方法来实例化它
在配置XML文件里面做如下配置
解释一下这个配置:
当代码执行到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的代码
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,我们可以发现更多对反射,注解等高级特性支持的方法
使用说明:
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>
延迟绑定很强大,反射,注解都可以支持
我用个实际例子来介绍:例如现在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,我们可以发现更多对反射,注解等高级特性支持的方法