0

我有一个名为 ChildPlugin 的子模块,我从主模块注入类,如下所示:

public class ChildPlugin {
    private ExampleClass demo;

    @Inject
    public void setDemo(ExampleClass demo) { 
        this.demo = demo;
    }
}

问题是我不知道主模块是否绑定ExampleClass,如果不是,Guice 在创建注入器时会抛出异常。我想要做的是让 Guice 通过null或者Optional.empty如果 ExampleClass 没有绑定。

我无权访问主模块,因此无法将活页夹更改为ExampleClassto OptionalBinder,我尝试了@Nullableand Optional<ExampleClass>inChildPlugin.setDemo方法,但没有成功。

4

1 回答 1

5

有两种方法可以做到这一点。

可选注入

使用 com.google.inject.Inject 注释。这一个允许您在注释上指定可选。看这个例子:

public class GuiceInjectOptional extends AbstractModule {

    @Override
    protected void configure() {

        // method 1: 
        bind(B.class).in(Singleton.class);

    }

    public static class A {

        private String name;
        // non null constructor so that A can't be instantiated automatically by guice
        public A(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "I am: " + name;
        }
    }

    public static class B {

        @Inject(optional=true)
        A obj;

        void run() {
            System.out.println("Object is: " + obj);
        }
    }

    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new GuiceInjectOptional());
        injector.getInstance(B.class).run();;
    }

}

B 类的注释表明 A 是可选的。它不会被注入。运行代码段打印:

Object is: null

方法2(这是你在guice 4+之后做的方式)。您可以指定可选绑定。如果您愿意,这些绑定甚至允许您定义默认值。然后你可以注入一个可选值,就像我写的这个片段一样:

public class GuiceInjectOptional extends AbstractModule {

    @Override
    protected void configure() {
        // set up optional binding for A.
        OptionalBinder.newOptionalBinder(binder(), A.class);

        bind(B.class).in(Singleton.class);
    }

    public static class A {

        private String name;
        // non null constructor so that A can't be instantiated automatically by guice
        public A(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "I am: " + name;
        }
    }

    public static class B {

        @Inject
        Optional<A> obj;

        void run() {
            System.out.println("Object is present: " + obj.isPresent());
            System.out.println("Object is: " + obj);
        }
    }

    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new GuiceInjectOptional());
        injector.getInstance(B.class).run();;
    }

}

Inject 注解现在是非可选的,但 guice 知道类 A 可能已绑定或未绑定。运行代码段将打印:

Object is present: false
Object is: Optional.empty

最后,您可以正常绑定 A 并且 guice 将注入它:

public class GuiceInjectOptional extends AbstractModule {

    @Override
    protected void configure() {
        // set up optional binding for A.
        OptionalBinder.newOptionalBinder(binder(), A.class);

        bind(A.class).toInstance(new A("Pandaa!"));
        bind(B.class).in(Singleton.class);
    }

    public static class A {

        private String name;
        // non null constructor so that A can't be instantiated automatically by guice
        public A(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "I am: " + name;
        }
    }

    public static class B {

        @Inject
        Optional<A> obj;

        void run() {
            System.out.println("Object is present: " + obj.isPresent());
            System.out.println("Object is: " + obj);
        }
    }

    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new GuiceInjectOptional());
        injector.getInstance(B.class).run();;
    }

}

以上将打印:

Object is present: true
Object is: Optional[I am: Pandaa!]

这就是您使用 guice 进行故障安全可选绑定的方式 :) 我希望这会有所帮助。

编辑:我刚刚看到了 guice-3 标签,所以你会想要使用可选的注释方法而不是可选的活页夹。使用可选注释,它将保持为空而不是可选值。

阿图尔

于 2016-08-12T09:44:22.793 回答