Guice笔记

<p>1、Hello World!</p>
<p><textarea cols="66" rows="38" name="code" class="java:collapse">1、定义Service
Service.java

public interface Service{
  public void sayHello();
}
2、定义实现类
ServiceImpl.java

public class ServiceImpl implements Service{
  @Override
  public String sayHello() {
    return "Hello World!";  
  }
}
3、客户端
Client.java
public class Client {
  //@Inject 也可以再这里注入
  public Service service;
  /*这里是在构造函数中注入了
    优点是可以再构造函数中完成一些初始化工作
     缺点是类的实例化与参数绑定,限制了实例化类的方式
  */
  @Inject
  public Client(Service service){
    this.service = service;
  }
  public void print(){
   System.out.println(service.say());
  }
}
4、测试类
public class Test extends TestCase{
  public void testGuice(){
    Injector inj = Guice.createInjector(new Module(){
      @Override
      public void configure(Binder binder){
        binder.bind(Service.class).to(ServiceImpl.class);
      }
    });
    Client client = inj.getInstance(Client.class);
    client.print();
  }
}</textarea></p>
<p></p>
<p>2、单例问题</p>
<p></p>
<p>在测试类中直接拿Service对象比较</p>
<p></p>
<p><textarea cols="71" rows="15" name="code" class="java">Service service = inj.getInstance(Service.class);
Service service2 =inj.getInstance(Service.class);
Assert.assertEquals(service.hashCode(),service2.hashCode());
//不等,每次都会返回一个新的实例

修改代码Module中的方法
...
binder.bind(Service.class).to(Serviceimpl.class).in(Scopes.SINGLETON);
...
//再次测试
Service service = inj.getInstance(Service.class);
Service service2 =inj.getInstance(Service.class);
Assert.assertEquals(service.hashCode(),service2.hashCode());
//相等,返回是同一个实例

//--------------------我是分割线 -----------------------------
//也可以通过在实现类上添加@Singleton标注来完成,
@Singleton
public class ServiceImpl implements Service{
  ...
}</textarea></p>
<p></p>
<p>3、返回的是正常的实例,未做转换和代理。</p>
<p></p>
<p><textarea cols="50" rows="15" name="code" class="java">Service service = inj.getInstance(Service.class);
System.out.println(service.getClass().getName());
//输出Service,是正常的实例,未做转换和代理。</textarea></p>
<p></p>
<p></p>
<p>4、无法绑定多个实现到一个借口</p>
<p></p>
<p><textarea cols="61" rows="15" name="code" class="c-sharp">再建一个实现类
public class ServiceImplAgain implements Service{
  ...
}
然后修改Module类
...
binder.bind(Service.class).to(ServiceImpl.class);
binder.bind(Service.class).to(ServiceImplAgain.class);
..
//系统报错</textarea></p>
<p></p>
<p>5、不可以自己绑定自己,但可以绑定子类到自己,也可以绑定到自己构造出来的实例上。</p>
<p></p>
<p><textarea cols="68" rows="18" name="code" class="c-sharp">...
binder.bind(ServiceImpl.class).to(ServiceImpl.class);
...
//报错 ,不可以自己绑定自己 Binding porins to itserlf

//--------------------我是分割线---------------------------

public class ServiceSubImpl extends ServiceImpl{
  ...
}
...
binder.bind(ServiceImpl.class).to(ServiceSubImpl.class);
...
/*运行正常,支持子类绑定,这样即使我们将一个实现类发布出去(尽管不推荐这么做),我们再后期仍然有拌饭替换实现类。*/

//--------------------我是分割线---------------------------
...
binder.bind(Service.class).to(new ServiceImpl());
...
//绑定到实例上
</textarea></p>
<p></p>
<p></p>
<p>5、可以Guice提供一个方式(Provider&lt;T&gt;),允许自己提供构造对象的方式。</p>
<p><textarea cols="79" rows="15" name="code" class="c-sharp">//方法一
...
binder.bind(Service.class).toProvider(new Provider&lt;Service&gt;() {
  @Override
  public Service get() {
    return new ServiceImpl();
  }
});
...
//方法二,或者直接编写类
public class ServiceProvider implements Provider&lt;Service&gt;{
  @Override
  public Service get(){
    return new ServiceImpl();
  }
}
//正常调用
...
binder.bind(Service.class).toProvider(ServiceProvider.class)
...
//方法三,也可以再借口上预定义
@ProvideBy(ServiceProvider.class)
public interface Service{
  ...
}
...
Service service = Guice.createInjector().getInstance(Client.class)
...
//方法四,当然也可以注入Provider,通过Guice获取后,调用get()获取Service的实例
public class ProviderServiceDemo {
  @Inject
  private Provider&lt;Service&gt; provider;

  public static void main(String[] args) {
    ProviderServiceDemo psd = Guice.createInjector(new Module() {
      @Override
      public void configure(Binder binder) {
        binder.bind(Service.class).toProvider(WwwServiceProvider.class);
      }}).getInstance(ProviderServiceDemo.class);
    psd.provider.get().execute();//我们每次get出来都是新对象
  }
}
</textarea></p>
<p></p>
<p></p>
<p>6、可以直接获取实例而不通过Modue绑定。</p>
<p><textarea cols="50" rows="15" name="code" class="java:nocontrols">Injector inj=  Guice.createInjector();
Service service = inj.getInstance(ServiceImpl.class);
System.out.println(service.sayHello());</textarea></p>
<p></p>
<p></p>
<p>7、使用注解实现注入,等于是默认实现类。</p>
<p></p>
<p><textarea cols="50" rows="15" name="code" class="java">@ImplementedBy(ServiceImpl.class)
public interface Service{
  String sayHello();
}

Injector inj = Guice.createInjector();
Service service = inj.getInstance(Service.class);
System.out.println(service.sayHello());
//使用Module关联 优先于 @ImplementedBy</textarea></p>
<p></p>
<p>8、静态属性注入</p>
<p></p>
<p><textarea cols="52" rows="15" name="code" class="java">@Inject
public Service service;
//运行正常

@Inject
public static Service service;
//如果是刚才的客户端代码,使用时报空指针异常。

//要这么写
public class Demo{
  @Inject
  private static Service service;
  public static void main(String[] args){
    Guice.createInjector(new Module(){
      @Override
      public void configure(Binder binder){
        binder.requestStaticInjection(Demo.class);
      }//这里请求了静态注入服务。
    });
    Demo.service.sayHello():
  }
}</textarea></p>
<p></p>
<p>9、构造函数注入可以自动注入多个参数</p>
<p></p>
<p><textarea cols="50" rows="15" name="code" class="java">...
@Inject
public Client(Service service,Service2 service2){
  this.service = service;
  this.service2 = service2;
}
...</textarea></p>
<p></p>
<p>10、使用setter注入</p>
<p></p>
<p><textarea cols="50" rows="15" name="code" class="java">...
@Inject
public void setService(Service service){
  this.service = service;
}
...</textarea></p>
<p></p>
<p></p>
<p>11、注入实例变量的属性</p>
<p></p>
<p><textarea cols="57" rows="15" name="code" class="java">public class Demo{
  @Inject
  private Service service;
  public static void main(String[] args){
    final Demo demo = new Demo();
    Guice.createInjector(new Module(){
      @Override
      public void configure(Binder binder){
        binder.requestInjection(demo);//想实例变量注入属性
      }
    });
    demo.service.sayHello();
  }
}
//更简便的方法
...
Guice.createInjector().injectMember(demo);//一句搞定
...</textarea></p>
<p></p>
<p></p>
<p>12、绑定多个服务</p>
<p></p>
<p><textarea cols="83" rows="15" name="code" class="c-sharp">public interface Service{
  void execute();
}

public class HomeService implements Service{
  @Override
  public void execute(){
    System.out.println("home");
  }
}

public class WwwService implements Service{
  @Override
  public void execute(){
    System.out.println("www");
  }
}
//这里需要定义2个注解
@Retention(RetentionPolicy.RUNTIME)
@Target({FIELD,PARAMETER})
@BindingAnnotation
public @interface Home {
}

@Retention(RetentionPolicy.RUNTIME)
@Target({FIELD,PARAMETER})
@BindingAnnotation
public @interface Www {
}

public class Demo {

  @Inject
  @Www
  private Service wwwService;

  @Inject
  @Home
  private Service homeService;

  public static void main(String[] args) {
    Demo demo = Guice.createInjector(new Module() {
      @Override
      public void configure(Binder binder) {
        binder.bind(Service.class).annotatedWith(Www.class).to(WwwService.class);
        binder.bind(Service.class).annotatedWith(Home.class).to(HomeService.class);
      }
      }).getInstance(Demo.class);
    demo.homeService.execute();
    demo.wwwService.execute();
}
}
</textarea></p>
<p></p>
<p>静态注入 多个服务</p>
<p></p>
<p><textarea cols="83" rows="15" name="code" class="java">public class StaticMultiInterfaceServiceDemo {
  @Inject
  @Www
  private static Service wwwService;

  @Inject
  @Home
  private static Service homeService;

  public static void main(String[] args) {
    Guice.createInjector(new Module() {
      @Override
      public void configure(Binder binder) {
        binder.bind(Service.class).annotatedWith(Www.class).to(WwwService.class);
        binder.bind(Service.class).annotatedWith(Home.class).to(HomeService.class);
        binder.requestStaticInjection(StaticMultiInterfaceServiceDemo.class);
      }
    });
  StaticMultiInterfaceServiceDemo.homeService.execute();
  StaticMultiInterfaceServiceDemo.wwwService.execute();
  }
}</textarea></p>
<p></p>
<p>太懒,不想写注解怎么办,用Names模板</p>
<p></p>
<p><textarea cols="91" rows="15" name="code" class="java">public class NoAnnotationMultiInterfaceServiceDemo {
  @Inject
  @Named("Www")
  private static Service wwwService;

  @Inject
  @Named("Home")
  private static Service homeService;

  public static void main(String[] args) {
    Guice.createInjector(new Module() {
      @Override
      public void configure(Binder binder) {
        binder.bind(Service.class).annotatedWith(Names.named("Www")).to(WwwService.class);
        binder.bind(Service.class).annotatedWith(Names.named("Home")).to(HomeService.class);
        binder.requestStaticInjection(NoAnnotationMultiInterfaceServiceDemo.class);
      }
    });
    NoAnnotationMultiInterfaceServiceDemo.homeService.execute();
    NoAnnotationMultiInterfaceServiceDemo.wwwService.execute();
  }
}</textarea></p>
<p></p>
<p></p>
<p>13、绑定常量</p>
<p><textarea cols="78" rows="15" name="code" class="java">public class ConstantInjectDemo {
 
  @Inject
  @Named("v")
  private int v;
  public static void main(String[] args) {
    ConstantInjectDemo cid = Guice.createInjector(new Module() {
      @Override
      public void configure(Binder binder) {
        binder.bindConstant().annotatedWith(Names.named("v")).to(12);
        //以下方法同样适用(其他基本类型全部适用)
        //binder.bind(int.class).annotatedWith(Names.named("v")).toInstance(12);


      }
      }).getInstance(ConstantInjectDemo.class);
    System.out.println(cid.v);
  }
}
</textarea></p>
<p></p>
<p></p>
<p>14、绑定Properties</p>
<p><textarea cols="79" rows="15" name="code" class="java">@Inject
@Named("web")
private String web;

public static void main(String[] args) {
  ConstantInjectDemo cid = Guice.createInjector(new Module() {
    @Override
    public void configure(Binder binder) {
      Properties properties= new Properties();
      properties.setProperty("web", "www.imxylz.cn");
      Names.bindProperties(binder, properties);
    }
  }).getInstance(ConstantInjectDemo.class);
  System.out.println(cid.web);
}
</textarea></p>

你可能感兴趣的:(Guice)