排版乱?请移步原文获得更好的阅读体验
1.背景最近项目中使用了guice作为依赖注入的框架。碰到一个如下的场景:
定义了一个从不同渠道输入数据的接口AbstractImporter,设计之初的目标是抽象从hdfs,kafka,DBMS等数据源输入数据处理。那么对应的实现就会有HdfsImporter,KafkaImporter,即一个接口对应多个实现。google官方的文档提供了两种实现方法:1.给每一个绑定对应写一个自定义注解,2.使用@Named注解。第二个方法的好处是不用为每个绑定写一个自定义注解,类似于spring中的@Resource,于是果断采用第二种方式,但是google文档上关于如何实现写的不是很详细,而且好多文章中给的都是类似下面的错误实现:
java 13行
public class PlayerModule implements Module{ public void configure(Binder binder) { binder.bind(Player.class).annotatedWith(Names.named("Good")).to( GoodPlayer.class); binder.bind(Player.class).annotatedWith(Names.named("Bad")).to( BadPlayer.class); } } //现在在客户端代码中,我们将使用 @Named() annotation来获取注释。 @Named("Good") Player goodPlayer = (Player)injector.getInstance(Player.class); @Named("Bad") Player badPlayer = (Player)injector.getInstance(Player.class);
一跑就会报“接口没有绑定实现类”的错误,非常的蛋疼!
2.总结后来受guice文档上简短代码片段的启发加上自己的领悟,终于解决了这个问题。回头想想导致整个问题的原因是自己盲目相信网上的文章且对guice作为一个依赖注入框架的认识不深导致的。下面贴出能正确运行的代码:
java 6行
//接口 package net.bigdataer.demo.juice; public interface People { public void setId(int id); }
java 9行
package net.bigdataer.demo.juice; //实现类 public class Student implements People { public void setId(int id) { System.out.println(id); } }
java 8行
package net.bigdataer.demo.juice; //实现类 public class Teacher implements People { public void setId(int id) { System.out.println(id); } }
java 13行
package net.bigdataer.demo.juice; import com.google.inject.Binder; import com.google.inject.Module; import com.google.inject.name.Names; //module类,绑定实现类到接口 public class JuiceModule implements Module { public void configure(Binder binder) { binder.bind(People.class).annotatedWith(Names.named("Teacher")).to(Teacher.class); binder.bind(People.class).annotatedWith(Names.named("Student")).to(Student.class); } }
重要的代码段,如何使用@Named绑定多个实现
java 29行
package net.bigdataer.demo.juice; import com.google.inject.Inject; import com.google.inject.name.Named; public class InjectionConfig { private People student; private People teacher; public People getStudent() { return student; } @Inject public void setStudent(@Named("Student") People student) { this.student = student; } public People getTeacher() { return teacher; } @Inject public void setTeacher(@Named("Teacher") People teacher) { this.teacher = teacher; } }
java 18行
package net.bigdataer.demo.juice; import com.google.inject.Guice; import com.google.inject.Injector; public class NameMain { public static void main(String[] args){ Injector injector = Guice.createInjector(new JuiceModule()); InjectionConfig config = injector.getInstance(InjectionConfig.class); People teacher = config.getTeacher(); teacher.setId(2); People student = config.getStudent(); student.setId(23); } }3.升华
因为guice框架是用在我的项目中的,而整个项目是用scala语言写的,所以我也测试了guice在scala中的使用。总体感觉就是配合scala的语法,用起来非常爽。贴一下对应java中InjectionConfig类的scala实现:
scala 21行
package net.bigdataer.demo.juice import com.google.inject.Inject import com.google.inject.name.Named class SInjectionConfig { //使用named注解绑定多个实现 @Inject @Named("Teacher") var teacher:SPeople = _ @Inject @Named("Student") var student:SPeople = _ //普通绑定,绑定一个实现 @Inject var log:Log = _ }
代码量不是一般的少。完整的demo放在了github上,地址:https://github.com/bigdataer01/scala-guice-demo
更多文章请关注微信公众号:bigdataer