【问题标题】:Decorator design pattern with Guice and Modules.override带有 Guice 和 Modules.override 的装饰器设计模式
【发布时间】:2021-08-06 09:26:09
【问题描述】:

假设我的ProductionModule 中有一个StringPrinter 对象:

private static interface StringPrinter {
    void print(String s) throws IOException;
}

private static class ProductionModule extends AbstractModule {
    @Provides
    StringPrinter productionPrinter() {
        return System.out::println;
    }
}

现在,我有一个调试模块,用于调试我的应用程序。我想装饰productionPrinter 对象并在productionPrinter 打印之前随机抛出异常。

private static class DebuggingModule extends AbstractModule {

    // I want productionPrinter here
    @Provides
    StringPrinter debuggingPrinterThatThrowsRandomlyExceptionToDebugExceptionHandling(
            StringPrinter productionPrinter) {
        // HOW TO GET productionPrinterHere?
        return string -> {
            if (Math.random() < 0.5)
                throw new IOException();
            productionPrinter.print(string);
        };
    }
}

当我用DebuggingModule 覆盖ProductionModule 时如何获取productionPrinter 对象?

查看完整示例和里面的 cmets:

public class GuiceDecorator {
    private static interface StringPrinter {
        void print(String s) throws IOException;
    }

    private static class ProductionModule extends AbstractModule {
        @Provides
        StringPrinter productionPrinter() {
            return System.out::println;
        }
    }

    private static class DebuggingModule extends AbstractModule {

        // I want productionPrinter here
        @Provides
        StringPrinter debuggingPrinterDecoratorThatThrowsRandomlyException(
                StringPrinter productionPrinter) {
            // HOW TO GET productionPrinter here?
            return string -> {
                if (Math.random() < 0.5)
                    throw new IOException();
                productionPrinter.print(string);
            };
        }
    }

    public static void main(String[] args) throws IOException {
        Module m = Modules.override(new ProductionModule()).with(new DebuggingModule());
        Injector injector = Guice.createInjector(m);
        StringPrinter printer = injector.getInstance(StringPrinter.class);
        printer.print("Hello world"); //I want to be using debuggingPrinter here
    }

}

当我运行它时,我得到一个异常。这个例外很奇怪,但很合理,因为 Guice 不能 @Inject 任何 StringPrinter 对象。

我能想到的唯一解决方案是使用限定符并绑定productionPrinter两次:

    private static class ProductionModule extends AbstractModule {
        @Provides
        StringPrinter productionPrinter() {
            return System.out::println;
        }

        @Provides
        @Named("inproduction")
        StringPrinter productionPrinter2() {
            return System.out::println;
        }
    }

    private static class DebuggingModule extends AbstractModule {

        @Provides
        StringPrinter debuggingPrinterThatThrowsRandomlyExceptionToDebugExceptionHandling(
                @Named("inproduction") StringPrinter productionPrinter) {
            return string -> {
                if (Math.random() < 0.5)
                    throw new IOException();
                productionPrinter.print(string);
            };
        }
    }

但我觉得这个解决方案很奇怪。有没有其他办法?

我的 Guice 版本:4.2.3

【问题讨论】:

    标签: java dependency-injection guice


    【解决方案1】:

    您可以使用method interceptor 来实现您的目标。

    对于您的示例,它可能如下所示:

    private static interface StringPrinter {
        void print(String s) throws IOException;
    }
    
    private static class ProductionModule extends AbstractModule {
        @Provides
        StringPrinter productionPrinter() {
            return System.out::println;
        }
    }
    
    private static class DebuggingModule extends AbstractModule {
        @Override
        protected void configure() {
            bindInterceptor(
                Matchers.subclassesOf(StringPrinter.class),
                Matchers.any(),
                invocation -> {
                    if (Math.random() < 0.5) {
                        throw new IOException();
                    }
                    return invocation.proceed();
                }
            );
        }
    }
    

    【讨论】:

    • 1+。我已经在使用 AOP,但我想知道是否还有其他问题。
    猜你喜欢
    • 1970-01-01
    • 2010-10-05
    • 1970-01-01
    • 1970-01-01
    • 2021-02-15
    • 1970-01-01
    • 2014-02-20
    • 2013-11-28
    • 1970-01-01
    相关资源
    最近更新 更多