Java 匕首2 vs注射器等级
我刚开始使用Dagger 2,我想知道它比我目前用来实现依赖注入的技术有什么优势 目前,为了实现DI,我创建了一个具有两种风格的项目,mock和prod。在这些风格中,我创建了一个名为Injector的类Java 匕首2 vs注射器等级,java,android,unit-testing,dependency-injection,dagger-2,Java,Android,Unit Testing,Dependency Injection,Dagger 2,我刚开始使用Dagger 2,我想知道它比我目前用来实现依赖注入的技术有什么优势 目前,为了实现DI,我创建了一个具有两种风格的项目,mock和prod。在这些风格中,我创建了一个名为Injector的类 //prod Injector public class Injector { public static INetworkLayer provideNetworkLayer() { return new ProductionNetworkLayer(); }
//prod Injector
public class Injector {
public static INetworkLayer provideNetworkLayer() {
return new ProductionNetworkLayer();
}
}
//mock Injector
public class Injector {
public static INetworkLayer provideNetworkLayer() {
return new MockNetworkLayer();
}
}
对于我需要注入的每个对象,Injector类都有一个静态方法。在我的应用程序代码中,我可以简单地编写:
INetworkLayer networkLayer = Injector.provideNetworkLayer();
这对于测试非常有用,因为在我的生产代码或测试代码中,我可以简单地告诉注入器我想要什么,并且根据我使用的构建变量,注入器将给我生产对象或模拟测试对象。如果我希望某个对象是单例对象,我只需要在Injector类中保存对它的引用,然后在调用provide…()时给出该引用
我已经开始在一个新项目中使用Dagger2,并且发现与我在上面演示的“Injector”类方法相比,设置mock/prod依赖项要复杂得多
匕首2与“注入器类”方法有何不同
有没有一个好方法可以使用Dagger2来提供模拟和prod类
我想知道它比我目前用来实现依赖注入的技术有什么优势
自动依赖关系图解析,以及通过添加范围注释来定义范围的提供程序
但您的示例可以轻松转换为可与Dagger2一起使用的示例,请看:
//prod Injector
@Module
public class NetworkModule {
@Provides
@Singleton
public static INetworkLayer provideNetworkLayer() {
return new ProductionNetworkLayer();
}
}
//mock Injector
@Module
public class NetworkModule {
@Provides
@Singleton
public static INetworkLayer provideNetworkLayer() {
return new MockNetworkLayer();
}
}
及
及
因为这样你就可以做到:
INetworkLayer networkLayer = Injector.get().provideNetworkLayer();
现在你可以问,“等一下,我已经做了,但是现在需要更多的代码来设置!” 这是因为你从来没有真正展示过如果你的依赖关系相互依赖会发生什么 比如说,
@Module
public class NetworkModule {
@Provides
@Singleton
public static INetworkLayer provideNetworkLayer(OkHttpClient okHttpClient) {
return new ProductionNetworkLayer(okHttpClient);
}
@Provides
@Singleton
public OkHttpClient provideOkHttpClient() {
return new /*create okHttpClient*/;
}
}
此外,您还可以使用@Inject
注释在一定程度上简化模块。虽然在使用接口时,这并不明显
@Singleton
public class ProductionNetworkLayer {
private OkHttpClient okHttpClient;
@Inject
public ProductionNetworkLayer(OkHttpClient okHttpClient) {
this.okHttpClient = okHttpClient;
}
}
@Module
public abstract class NetworkModule {
@Binds
public abstract INetworkLayer provideNetworkLayer(ProductionNetworkLayer productionNetworkLayer);
// same as `public INetworkLayer prov(ProductionNetworkLayer prod) { return prod; }`
@Provides
@Singleton
public OkHttpClient provideOkHttpClient() {
return new /*create okHttpClient*/;
}
}
我想知道它比我目前用来实现依赖注入的技术有什么优势
自动依赖关系图解析,以及通过添加范围注释来定义范围的提供程序
但您的示例可以轻松转换为可与Dagger2一起使用的示例,请看:
//prod Injector
@Module
public class NetworkModule {
@Provides
@Singleton
public static INetworkLayer provideNetworkLayer() {
return new ProductionNetworkLayer();
}
}
//mock Injector
@Module
public class NetworkModule {
@Provides
@Singleton
public static INetworkLayer provideNetworkLayer() {
return new MockNetworkLayer();
}
}
及
及
因为这样你就可以做到:
INetworkLayer networkLayer = Injector.get().provideNetworkLayer();
现在你可以问,“等一下,我已经做了,但是现在需要更多的代码来设置!” 这是因为你从来没有真正展示过如果你的依赖关系相互依赖会发生什么 比如说,
@Module
public class NetworkModule {
@Provides
@Singleton
public static INetworkLayer provideNetworkLayer(OkHttpClient okHttpClient) {
return new ProductionNetworkLayer(okHttpClient);
}
@Provides
@Singleton
public OkHttpClient provideOkHttpClient() {
return new /*create okHttpClient*/;
}
}
此外,您还可以使用@Inject
注释在一定程度上简化模块。虽然在使用接口时,这并不明显
@Singleton
public class ProductionNetworkLayer {
private OkHttpClient okHttpClient;
@Inject
public ProductionNetworkLayer(OkHttpClient okHttpClient) {
this.okHttpClient = okHttpClient;
}
}
@Module
public abstract class NetworkModule {
@Binds
public abstract INetworkLayer provideNetworkLayer(ProductionNetworkLayer productionNetworkLayer);
// same as `public INetworkLayer prov(ProductionNetworkLayer prod) { return prod; }`
@Provides
@Singleton
public OkHttpClient provideOkHttpClient() {
return new /*create okHttpClient*/;
}
}
您的方式更像服务定位器。我写了一篇比较SL和DI的文章,其中我还提到了交换依赖项的链接时间自由度。我写了一篇比较SL和DI的文章,其中还提到了交换依赖关系的链接时间自由度。checkout“自动依赖关系图解析”这是否意味着Dagger可以查看带有@Provides注释的所有方法签名,并连接正确的方法,以便某些方法的返回类型提供其他方法的参数?是的!就是这样,就像上面的“okhttpclient”示例一样。但只要模块属于同一个组件,它就可以跨模块工作,而且它适用于“带有
@Inject
注释的构造函数的具体类型,这些构造函数要么没有范围,要么与组件在同一范围内”,现在我想起来了,在这个场景中,您真正想要的是有一种味道的SingletonComponent
类,并将不同的模块绑定到其中。这就是您获得初始模拟/prodInjector
设置的方式。因此,每种口味都有一个SingletonComponent(SC),每个SC都会指定要使用的模块。因此,prod-SC将指定包含prod依赖项的模块,mock-SC将指定包含mock依赖项的模块。然后,由于它们都被称为SC,并且模块使用相同的名称,那么在代码的其余部分,您可以只调用DaggerSingletonComponent.build().netModule(新netModule()),并且您得到的是真实对象还是模拟对象将取决于项目设置为哪种风格?听起来对吗?“自动依赖关系图解析”这是否意味着Dagger可以使用@Provides注释查看所有方法签名,并连接正确的方法签名,以便某些方法的返回类型提供其他方法的参数?是的!就是这样,就像上面的“okhttpclient”示例一样。但只要模块属于同一个组件,它就可以跨模块工作,而且它适用于“带有@Inject
注释的构造函数的具体类型,这些构造函数要么没有范围,要么与组件在同一范围内”,现在我想起来了,在这个场景中,您真正想要的是有一种味道的SingletonComponent
类,并将不同的模块绑定到其中。这就是您获得初始模拟/prodInjector
设置的方式。因此,每种口味都有一个SingletonComponent(SC),每个SC都会指定要使用的模块。因此,prod-SC将指定包含prod依赖项的模块,mock-SC将指定包含mock依赖项的模块。然后,由于它们都被称为SC,并且模块使用相同的名称,那么在代码的其余部分,您可以只调用DaggerSingletonComponent.build().netModule(新netModule()),并且您得到的是真实对象还是模拟对象将取决于项目设置为哪种风格?听起来对吗?