4.Guice实战案例服务

2022-04-07  本文已影响0人  洛神灬殇

public static void main(String[] args) {

Injector injector = Guice.createInjector(new BindModule());

DogEgg dogEgg = injector.getInstance(DogEgg.class);

System.out.println(dogEgg.service);

}

interface Service {}

public static class DefaultService implements Service {}

public static class DogEgg {

// 告诉Guice,这里要注入东西,具体的注入规则从Module里找吧

@Inject

public Service service;

}

public static class BindModule implements Module {

@Override

public void configure(Binder binder) {

    // 在注入的时候,遇到Service接口类型,全部注入成DefaultService实例

    binder.bind(Service.class).to(DefaultService.class);

}

}

@BindingAnnotation

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})

public @interface DefaultAnnotation{}

public static void main(String[] args) {

Injector injector = Guice.createInjector(new BindModule());

DogEgg dogEgg = injector.getInstance(DogEgg.class);

System.out.println(dogEgg.service);

System.out.println(dogEgg.service2);

}

interface Service {}

public static class DefaultService implements Service {}

public static class DefaultService2 implements Service {}

public static class DogEgg {

@Inject

@DefaultAnnotation

// 使用自定义注解标识该字段需要DefaultService实例

public Service service;

@Inject // 没有自定义注解,那就注入DefaultService2实例

public Service service2;

}

public static class BindModule implements Module {

@Override

public void configure(Binder binder) {

    binder.bind(Service.class).annotatedWith(DefaultAnnotation.class).to(DefaultService.class).

     in(Scopes.SINGLETON);

    binder.bind(Service.class).to(DefaultService2.class);

}

}

public static void main(String[] args) {

Injector injector = Guice.createInjector(new BindModule());

DogEgg dogEgg = injector.getInstance(DogEgg.class);

System.out.println(dogEgg.service);

System.out.println(dogEgg.service2);

System.out.println(dogEgg.service3);

}

interface Service {}

public static class DefaultService implements Service {}

public static class DefaultService2 implements Service {}

public static class DogEgg {

@Inject

@Named("service1")

// 注意这里的@Named注解

public Service service;

@Inject

@Named("service2") // 注意这里的@Named注解

public Service service2;

@Inject

public Service service3; // 注意这里的没有@Named注解!!!

}

public static class BindModule implements Module {

@Override

public void configure(Binder binder) {

    // 被@Named("service1")修饰的,给注入DefaultService实例

    binder.bind(Service.class).annotatedWith(Names.named("service1"))

            .to(DefaultService.class);

    // 被@Named("service2")修饰的,给注入DefaultService2实例

    binder.bind(Service.class).annotatedWith(Names.named("service2"))

            .to(DefaultService2.class);

    // 默认给注入DefaultService实例

    binder.bind(Service.class).to(DefaultService.class);

}

}

DefaultService@fad74ee

DefaultService2@1a1d6a08

DefaultService@37d31475 // 和第一行的DefaultService实例不是一个?!

   人家Spring可以配置单例还是原型,Guice也可以,在bind的时候指定一下就行,像上面那样不指定任何Scope的时候,每次注入时都会创建新实例!

public static class DogEgg {

@Inject

@Named("service1")

public Service service;

@Inject

@Named("service1")

public Service service5;

@Inject

@Named("service2")

public Service service2;

@Inject

public Service service3;

@Inject

public Service service4;

}

public static class BindModule implements Module {

@Override

public void configure(Binder binder) {

    binder.bind(Service.class).annotatedWith(Names.named("service1"))

            .to(DefaultService.class).in(Scopes.SINGLETON); // 这里指定了Scope

    binder.bind(Service.class).annotatedWith(Names.named("service2"))

            .to(DefaultService2.class);

    binder.bind(Service.class).to(DefaultService.class).in(Scopes.SINGLETON); // 这里也指定了Scope

}

}

输出次序为service1、service5、service2、service3、service4如下:

DefaultService@ed9d034

DefaultService@ed9d034 // service1和service5是一个对象

DefaultService2@6121c9d6

DefaultService@87f383f

DefaultService@87f383f // service3和service4是一个对象,但是与service1和service2不相同

上面这波输出也告诉我们,Guice的单例是按照binding划分的。

如果要全局单例,可以使用@Singleton注解,代码如下:

@Singleton

// 这个注解告诉Guice,该实现全局单例

public static class DefaultService implements Service {}

public static class DefaultService2 implements Service {}

public static class DogEgg {

@Inject

@Named("service1")

public Service service;

@Inject

@Named("service1")

public Service service5;

@Inject

@Named("service2")

public Service service2;

@Inject

public Service service3;

@Inject

public Service service4;

}

public static class BindModule implements Module {

@Override

public void configure(Binder binder) {

    binder.bind(Service.class).annotatedWith(Names.named("service1")).to(DefaultService.class);

    // 这里没有再指定Scope

    binder.bind(Service.class).annotatedWith(Names.named("service2")).to(DefaultService2.class);

    binder.bind(Service.class).to(DefaultService.class);  // 这里没有再指定Scope

}

}

   这里的Singleton到底是懒汉模式还是饿汉模式呢?这个也是可以配置的,默认是懒汉模式,就是延迟加载!!!其实懒汉和饿汉模式在代码跑起来之后,没啥太大差别,毕竟该创建的都创建了。要是想详细理解的话,翻翻文档吧,这个不是特别重要。除了Singleton之外,还有Scope,例如ServletScopes.REQUEST,也去看文档吧,这个也不是特别重要。

除了上面介绍的字段注入,Guice还可以通过构造注入:

public static void main(String[] args) { 

    Injector injector = Guice.createInjector(new BindModule());

    DogEgg dogEgg = injector.getInstance(DogEgg.class);

    System.out.println(dogEgg.service);

    System.out.println(dogEgg.service5);

    System.out.println(dogEgg.service2);

    System.out.println(dogEgg.service3);

    System.out.println(dogEgg.service4);

}

interface Service {}

@Singleton

public static class DefaultService implements Service {

private String name;

private TestArg testArg;

public DefaultService(String name, TestArg testArg) { // 构造函数

    this.name = name;

    this.testArg = testArg;

}

public DefaultService() {} // 无参构造函数

@Override

public String toString() { // 这里专门加了一个hashCode(),用于区分是不是一个对象

    return hashCode() +" DefaultService{" +

            "name='" + name + '\'' +

            ", testArg=" + testArg +

            '}';

}

}

public static class DefaultService2 implements Service {}

public static class DogEgg {

@Inject

@Named("service1")

public Service service;

@Inject

@Named("service1")

public Service service5;

@Inject

@Named("service2")

public Service service2;

@Inject

public Service service3;

@Inject

public Service service4;

}

public static class TestArg {

}

public static class BindModule implements Module {

@Override

public void configure(Binder binder) {

    // 碰到@Named("service1")注解修饰的注入,继续走无参构造函数

    binder.bind(Service.class).annotatedWith(Names.named("service1")).to(DefaultService.class);

    binder.bind(Service.class).annotatedWith(Names.named("service2"))

            .to(DefaultService2.class);

    // binder.bind(Service.class).to(DefaultService.class);

    // 这与下面走构造函数的binding冲突,Guice不知道该走哪个构造方法

    try {

        binder.bind(Service.class) // 没有@Named("service1")注解修饰的注入,走构造方法

                .toConstructor(DefaultService.class

                        .getConstructor(String.class, TestArg.class));

    } catch (NoSuchMethodException e) {

        e.printStackTrace();

    }

}

}

上一篇下一篇

猜你喜欢

热点阅读