有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Guice从覆盖中访问原始值

测试中我想包装另一个模块已经提供的对象。 基本上是这样的(但有效):

Guice.createInjector(Modules.override(
    // This module lives somewhere else and I rather can't change it
    new AbstractModule() {
        @Override
        protected void configure() {
          bind(Ticker.class).to(TickerImpl.class);
        }

        @Provides @Singleton
        public Tacker getTacker(Ticker ticker) {
          return new Tacker(ticker);
        }
    }).with(new AbstractModule() {
        @Override
        protected void configure() {
        }

        // This doesn't work. oldTicker is an instance of 
        // DelegatingInvocationHandler that references the
        // result of this function causing infinite recursion.
        @Provides @Singleton Ticker getTicker(Ticker oldTicker) {
          return new SpyingTicker(oldTicker);
        }
    })).getInstance(Tacker.class).tack();

有没有办法做到这一点?我找到的唯一解决方案是在覆盖中执行此操作:

        @Provides @Singleton
        public Tacker getTacker(Ticker ticker) {
          return new Tacker(new SpyingTicker(ticker));
        }

这是不理想的,因为它复制了原始模块的逻辑,并且没有在任何地方取代“Ticker”的注入(只是在创建“Tacker”时)


共 (1) 个答案

  1. # 1 楼答案

    因为这是一个测试,所以最好的解决方案是简单地替换另一个团队提供的整个模块。这允许您以自己认为合适的方式更改绑定。然而,我可以理解,如果只有一个改变,你为什么不想这么做

    如果你能让另一个团队做出一些小的改变,我可以尝试以下方法:

    public class ProductionModule extends AbstractModule {
        protected void configure() {
            // snip
        }
    
        @Provides @Singleton
        protected MyObject provideMyObject(Dependency dependency) {
            return delegateProvide(dependency);
        }
    
        // note the lack of annotations
        protected MyObject delegateProvide(Dependency dependency) {
            return new MyObject(dependency);
        }
    }
    

    然后,在你的测试中:

    public class TestModule extends ProductionModule {
       @Override
       protected MyObject delegateProvide(Dependency dependency) {
           return new MyObjectSpy(super.delegateProvide(dependency));
       }
    }