依赖注入是一种软件开发概念,其中为对象提供创建所需的所有对象或值。 GWT 用户对 GIN 已经很熟悉了,但这最后一个已经被弃用并且不再被支持,所以目前使用 GIN 的应用程序真的需要告别了。 Dagger 是 GWT 的新依赖注入框架。对于那些不熟悉该框架的人,Dagger 旨在为 Android 提供 DI,但现在用于通用 DI。它也适用于 GWT。在这篇文章中,我们将简要介绍 Dagger 以及如何使用 Dagger 为 GWT 项目设置 DI。
与使用生成器(将来某个时间将从 GWT 中删除)的 GIN 不同,Dagger 使用编译时注释处理器。使用 Dagger 的项目在升级 GWT 版本时会遇到更少的麻烦。另一方面,DI 通常会引入复杂性,因此很难调试注入过程中发生的错误。众所周知,GIN 堆栈跟踪有时是不可读的。 Dagger 的目标之一就是减少这个缺点。 Dagger 生成的代码接近于人类编写的代码,因此更容易理解幕后发生的事情,因此开发人员在调试时会更少头疼。
<dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> <version>1</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.google.dagger</groupId> <artifactId>dagger-gwt</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.google.dagger</groupId> <artifactId>dagger-compiler</artifactId> <version>2.5</version> <scope>provided</scope> </dependency>
Dagger 需要 javax.inject 注释在编译时放在类路径上。另外,.gwt.xml中需要添加Dagger模块:
<inherits name="dagger.Dagger"> </inherits>
那么如果你使用的是maven,你需要使用高于3.5.1版本的compiler plugin才能在编译目标被调用时自动执行注解编译。否则,您将需要在插件配置中同时指定 annotationProcessors 和 annotationProcessorsPaths。可选地,dagger-compiler 编译器可以从依赖项中删除并添加到 annotationProcessorsPaths,如 SO 中的 Thomas Broyer 所指定:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>1.7</source> <target>1.7</target> <annotationProcessorPaths> <path> <groupId>com.google.dagger</groupId> <artifactId>dagger-compiler</artifactId> <version>${dagger.gwt.version}</version> </path> </annotationProcessorPaths> </configuration> </plugin>
还值得注意的是,在开发模式下,每次注入的类发生变化时都需要重新运行注释处理器。在 maven 下,注释处理器可以使用 process-classes 目标运行。我没有测试过 Gradle,但是使用 Gradle 的概念应该是相同的。
假设我们有一个压缩图片的服务。该服务依赖于另外两个服务:一个是下载图片的服务,一个是压缩后上传图片的服务。所有对象都有零参数构造函数。
public class ImageCompressor { @Inject public ImageDownloader downloader; @Inject public ImageUploader uploader; @Inject public ImageCompressor(){ } public void compress(String url) { downloader.download(url); GWT.log("compressing image"); uploader.upload(url); } }
public class ImageDownloader { @Inject public ImageDownloader() { } public void download(String url) { GWT.log("downloading image at " + url); } }
public class ImageUploader { @Inject public ImageUploader() { } public void upload(String url) { GWT.log("uploading compresesed image at " + url); } }
如果您需要特殊设置来构造对象,例如设置一些值或指定构造函数参数,那么您需要创建一个模块。假设我们需要为 ImageDownloader 对象提供超时值:
public class ImageDownloader { int timeout; //@Inject we cannot use inject on the constructor anymore public ImageDownloader(int timeout) { this.timeout = timeout; } public void download(String url) { GWT.log("downloading image at " + url); } }
然后我们需要指定一个模块来提供我们的 ImageDownloader:
@Module public class ImageCompressionModule { @Provides public ImageDownloader getImageDowloader(){ return new ImageDownloader(15); }
现在我们定义了模块和对象,我们将创建用于获取注入对象实例的 DI 组件。
@Component(modules=ImageCompressionModule.class) public interface AppComponent { ImageCompressor getImageCompressor(); }
我们的应用程序组件的实例可以通过以下方式获取:
AppComponent component = DaggerAppComponent.builder() .imageCompressionModule(new ImageCompressionModule()) .build();
如果您使用的是 IDE,那么您会注意到它抱怨 DaggerAppComponent。这很正常,因为 DaggerAppComponent 只有在运行注释处理器后才可用。
最后,我们可以使用我们的对象:
ImageCompressor compressor = component.getImageCompressor(); compressor.compress("http://www.g-widgets.com/GWTcon.jpg");
结果:
downloading image at http://www.g-widgets.com/GWTcon.jpg compressing image uploading compressed image to http://www.g-widgets.com/GWTcon.jpg
Dagger 2 是 GWT 的下一代依赖注入。我们已经在这篇文章中看到了该框架的基本功能。更多高级 DI 功能可以在 Dagger 的主要用户指南中找到:https://google.github.io/dagger/users-guide。 Dagger 的 GWT 版本与后端版本的工作方式相同:代码可以在客户端和服务器端工作,因此将 DI 移植到后端可能会很有用,以防在 JVM 中调试时出现问题。
完整代码位于:https://github.com/zak905/dagger2-gwt-example
标签2: Java教程地址:https://www.cundage.com/article/jcg-dependency-injection-gwt-using-dagger-2.html