我正在使用 Guice 学习依赖注入(inject)。我试图了解在使用依赖项注入(inject)框架进行编程时是否有推荐的方法来实现静态类常量。
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进行绑定(bind),并从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。通过依赖注入(inject),我发现注释需要是唯一的。前任。 @Named("cars.huracan.cartype")。如果该模块要与其他模块组合以创建主应用程序模块,则它还需要是全局唯一的。所以最后我发现自己给出了在注释中放入的字符串,或者我创建的自定义注释的名称,与 CLASS.FIELD 结构具有相同的含义。
- 这是正确的吗?但随后我失去了编程语言的“命名空间”功能,并且我必须手动确保每个字符串键或注释名称在全局范围内都是唯一的。
对此事的任何想法将不胜感激。
最佳答案
Is this the right programming model ? Is there suppose to be a Guice model for every class you want to store static constants ? Or create only one giant main app module for everything ? What is the semantic correlation between a module and a class ?
是的。 :-)
它可以是双向的。对于可能仅由一个类使用的依赖项,有一个专门用于该类的模块并将其安装在更高级别是有意义的。在其他情况下,在最高级别模块,甚至在单独的公共(public)/共享模块中绑定(bind)某些常量会更有意义。物理上只有一个大模块;从逻辑上讲,您如何布局将取决于个人喜好和当前的问题,就像任何应用程序代码的架构一样。
But then I am losing the programing language "namespace" feature and I have to manually make sure every string key or annotation name is unique globally.
如果您对注释使用自定义@BindingAnnotation
,那么您不必再担心命名空间冲突。 doc甚至触及主题:
Since the compiler can't check the string, we recommend using
@Named
sparingly.
这是替代版本:
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"));
}
}
请注意,我用显式字符串绑定(bind)替换了您对 bindConstant
的使用。我对 bindConstant
的行为了解不够,不知道它是否允许重复使用与我所做的相同的注释。但我想指出的是,一般来说(至少在像我一样使用显式类绑定(bind)时),这个版本不仅可以让您获得命名空间安全,还说明您不需要为每种数据类型使用单独的名称/注释。您可以在同一模块中针对十几个不同的依赖项重用 @Huracan
,只要每个依赖项都是不同的类型。
关于java - 如何使用依赖注入(inject)模式实现类常量静态字段声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25587409/