儿童模块的故障安全注射器。谷歌guice中的可选绑定

时间:2016-08-11 22:35:27

标签: java dependency-injection guice optional-binding

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

public class ChildPlugin {
    private ExampleClass demo;

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

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

我无法访问主模块,因此我无法将ExampleClass的活页夹更改为OptionalBinder,我在@Nullable方法中尝试了Optional<ExampleClass>ChildPlugin.setDemo但它没有用。

1 个答案:

答案 0 :(得分:1)

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

可选注射

使用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标签,因此您需要使用可选的注释方法而不是可选的绑定器。使用可选的注释,它将保持为null而不是可选值。

阿图尔