【问题标题】:How to implement a class constant static fields declarations with dependency injection pattern如何使用依赖注入模式实现类常量静态字段声明
【发布时间】:2014-08-30 22:53:32
【问题描述】:

我正在学习 Guice 的依赖注入。我试图了解在使用依赖注入框架进行编程时是否有推荐的方法来实现静态类常量。

Huracan 类第一版:

public class Huracan implements Car {
    public static final URL COMPANY_URL;
    public static final String CAR_TYPE = "sports car";

    static {
        try {
            COMPANY_URL = new URL("www.lamborghini.com");   

        } catch (MalformedURLException e) {
            e.printStackTrace();
            throw new Error(e);
        }
    }   

    public void drive() {
        System.out.println("Lamborghini Huracan " + CAR_TYPE + " driving!" );
    }
}

我可以创建一个模块 - HuracanModule - 在那里我可以使用 bindConstant 和 bind toInstance 进行绑定,并从 Huracan 类中删除静态常量声明。

Guice Huracan 模块:

public class HuracanModule extends AbstractModule {
    @Override
    protected void configure() {
        bindConstant().annotatedWith(Names.named("cars.huracan.cartype")).to("sports car");
        bind(URL.class).annotatedWith(Names.named("cars.huracan.company_url")).
          toInstance(new URL("www.lamborghini.com"));
    }   
}

Huracan 类第二版:

public class Huracan implements Car {           
    private final String CAR_TYPE;
    private final URL COMPANY_URL;

    public Huracan( @Named("cars.huracan.cartype") String carType, 
                    @Named("cars.huracan.comany_url") URL companyUrl ) {
            this.CAR_TYPE = carType;
            this.COMPANY_URL = companyUrl;
    }

    public void drive() {
            System.out.println("Lamborghini Huracan " + CAR_TYPE + " driving!" );
    }
}

我了解这使您可以灵活地在不同场景中操作常量。但我觉得我错过了一些东西。

  • 这是正确的编程模型吗?是否假设您要存储静态常量的每个类都有一个 Guice 模型?还是只为所有内容创建一个巨大的主应用程序模块?模块和类之间的语义相关性是什么?

通过在类上使用静态常量声明,知道如何唯一地引用它们的负担由编程语言本身处理。前任。 Huracan.CAR_TYPE。通过依赖注入,我发现注释需要是唯一的。前任。 @Named("cars.huracan.cartype")。如果模块要与其他模块组合以创建主应用程序模块,它还需要在全局范围内是唯一的。所以最后我发现自己给出了我放在注释中的字符串,或者我创建的自定义注释的名称,与 CLASS.FIELD 结构的含义相同。

  • 正确吗?但是后来我失去了编程语言的“命名空间”功能,我必须手动确保每个字符串键或注释名称在全球范围内都是唯一的。

对此事的任何想法将不胜感激。

【问题讨论】:

    标签: java dependency-injection static constants guice


    【解决方案1】:

    这是正确的编程模型吗?是否假设您要存储静态常量的每个类都有一个 Guice 模型?还是只为所有内容创建一个巨大的主应用程序模块?模块和类之间的语义相关性是什么?

    是的。 :-)

    它可以双向进行。对于可能仅由一个类使用的依赖项,为该类创建一个模块并将其安装在更高级别是有意义的。在其他情况下,将某些常量绑定在最高级别的模块甚至在单独的公共/共享模块中会更有意义。物理上只有一个大模块;从逻辑上讲,您如何布局将取决于个人偏好和手头的问题,就像任何应用程序代码的架构一样。

    但后来我失去了编程语言的“命名空间”功能,我必须手动确保每个字符串键或注释名称在全球范围内都是唯一的。

    如果您为注释使用自定义@BindingAnnotation,那么您不必再担心命名空间冲突。上面的doc 甚至触及到了这个话题:

    由于编译器无法检查字符串,我们建议使用@Named谨慎使用。

    这是替代版本:

    public class Huracan implements Car {           
        private final String CAR_TYPE;
        private final URL COMPANY_URL;
    
        @BindingAnnotation
        @Retention(RUNTIME)
        public @interface HuracanCar {}
    
        public Huracan( @HuracanCar String carType, 
                        @HuracanCar URL companyUrl ) {
            this.CAR_TYPE = carType;
            this.COMPANY_URL = companyUrl;
        }
    }
    

    还有模块:

    public class HuracanModule extends AbstractModule {
        @Override
        protected void configure() {
            bind(String.class).annotatedWith(HuracanCar.class).to("sports car");
            bind(URL.class).annotatedWith(HuracanCar.class).
              toInstance(new URL("www.lamborghini.com"));
        }   
    }
    

    请注意,我将您对bindConstant 的使用替换为显式字符串绑定。我不太了解bindConstant 的行为方式,不知道它是否允许重复使用与我正在做的相同的注释。但我想说的是,总的来说(至少在像我这样使用显式类绑定时),这个版本不仅可以确保命名空间安全,还说明您不需要为每种数据类型单独命名/注解.您可以在同一个模块中为十几个不同的依赖项重用@Huracan,只要每个依赖项的类型不同。

    【讨论】:

    • 谢谢!我正在研究相同的路径,以带有 value 属性的内部注释类结束,因此我可以绑定到类中相同类型的不同字段。很像“命名(字符串名称)”。不喜欢字符串,所以我在单独的字段中放置了一个内部枚举。但这需要实现一个自定义注释实现,就像 Guice NamedImpl 这有点矫枉过正:)。如果没有其他神奇的答案,我会选择这个答案:)
    • 是的,最终在类中为我想要表示的每个数据字段使用了单独的注释。就几行。另一方面,自定义注释方法需要每次在其中编写每个类,因为无法在注释接口上进行泛型。
    猜你喜欢
    • 1970-01-01
    • 2016-08-28
    • 2017-11-11
    • 1970-01-01
    • 2019-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-22
    相关资源
    最近更新 更多