子模块的故障安全注入器。 google guice 中的可选绑定

Posted

技术标签:

【中文标题】子模块的故障安全注入器。 google guice 中的可选绑定【英文标题】:Fail-safe injector for child modules. Optional bindings in google guice 【发布时间】:2016-08-11 22:35:26 【问题描述】:

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

public class ChildPlugin 
    private ExampleClass demo;

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

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

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

【问题讨论】:

【参考方案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 是可选的。它不会被注入。运行 sn-p 打印:

Object is: null

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

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 可能已绑定或未绑定。 运行 sn -p 将打印:

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 标签,所以你会想要使用可选的注释方法而不是可选的活页夹。使用可选注释,它将保持为空而不是可选值。

阿图尔

【讨论】:

感谢您的详细解释。我实际上使用的是 guice 4,Optional 的问题是必须在父模块中设置 OptionalBinder 并且我无权访问父模块,如果我只是在子注入器中使用 Optional 而父模块没有使用 OptionalBinder,Guice 抱怨绑定不存在。但是我不知道您的第一个解决方案,因为我使用的是 javax Injector。该解决方案对我有用,谢谢! 您应该能够在您的子模块中使用自己的可选绑定,并且始终将其放在那里。如果父模块添加了绑定,您的可选模块什么也不做,否则它将使用您父模块中绑定的任何内容。

以上是关于子模块的故障安全注入器。 google guice 中的可选绑定的主要内容,如果未能解决你的问题,请参考以下文章

JUnit测试中的Guice注入器[关闭]

如何从 Guice 的注入器中检索带注释的实例?

史上最好用的依赖注入框架Google Guice转

Guice 学习常量和属性的注入( Constant and Property Inject)

Google 开源的依赖注入库,比 Spring 更小更快!

Google Guice 与 JSR-299 CDI / Weld