我正在编写一个小型Web服务器,它需要一个配置文件,其中包含各种不同的选项:运行多少个线程,哪个类处理每个文件扩展名,哪个文件默认显示等等等等等等等等等等。向前。为了表示这一点,我将配置文件解析为包含所有这些设置的Configuration
对象,主类保存此对象。
但是,几乎每个服务器级别都需要配置数据 - 类中类的类......
我的问题是,在这里使用的最佳做法是什么?我应该将配置作为许多类的参数并来回传递吗?我应该把它变成单身吗?还有其他我没有看到的解决方案吗?
答案 0 :(得分:4)
使用Guice! Guice是一个依赖注入框架,它有效地取代了你对new关键字的使用。您可以在模块中定义对象绑定,如下所示:
bind(Configuration.class).to(MySpecificConfiguration.class);
bind(WebServer.class).to(MySpecificWebServerImplementation.class);
然后,不要直接新建WebServer
,而是让Guice为你做这件事:
WebServer ws = Guice.createInjector(yourModule).getInstance(WebServer.class);
这将为你神奇地创造MySpecificWebServerImplementation
。如果MySpecificWebServerImplementation
定义如下:
public class MySpecificWebServerImplementation {
@Inject
public MySpecificWebServerImplementation(Configuration configuration) {
}
}
然后MySpecificWebServerImplementation
将自动获得配置,您不必担心传递它。
答案 1 :(得分:2)
虽然Singletons
由于各种原因不再受到许多专业人士的青睐 - 我认为使用Ssingleton仍有一个很好的用例。
然而 - 问问自己,网络服务器的要求是否真的需要服务器所有方面的单一通用配置。如果是的话 - 他们很快就有可能改变? 例如 - 假设您的服务器托管3个网站。现在你被要求对其中一个设置带宽限制 - 你将如何配置它?
我真的很喜欢一个好的单例 - 虽然在多线程环境中初始化它时你必须要考虑整个线程安全问题(虽然听起来你不会有这个问题,因为你不会有多个线程在初始化之前。
请注意,单身人士居住在ClassLoader
内,如果您有多个ClassLoader
(例如,您加载的每个.war
),您将拥有此“{{1}的多个副本}}”。
考虑服务器的所有方面,如果它非常简单 - Singleton
将为您节省很多麻烦 - 并且会使代码更易于维护和读取。
正如在一个或两个答案中已经提到的 - 依赖注入是Singleton
的一个很好的替代方案 - 它们可以帮助您简化JUnits。
关于JUnit的一个注释,我理解(还没有尝试)Singleton
可以允许你在测试运行期间替换实际的实现,所以你仍然可以为不同的场景创建不同的JUnit测试用例修改您的Mockit
是可测试的。
答案 2 :(得分:1)
使它成为一个单身人士似乎是一个合理的解决方案。我认为将配置作为参数传递给其他类构造函数或方法调用是错误的,因为这会污染方法参数并使它们变得不必要地复杂。
如果你决定制作一个单例,那么我建议你设计一种机制,你可以将配置的新实例注入单例类,这样单例就不会让你的单元测试很难运行。 / p>
答案 3 :(得分:1)
传递Configuration
的实例会给代码增加许多不必要的混乱。 Singleton是一个好主意或添加某种 Manager 类,它提供所有这些共享资源,如配置数据。
如果你选择单身人士,请考虑实施枚举模式:
public enum Config{ DATA;
private int value1;
private int value2;
private int value3;
public load(File configFile) {
// some magic to store the values
}
public int getValue1() {return value1;}
public int getValue2() {return value2;}
public int getValue3() {return value3;}
}
您可以在代码中的任何位置使用它:
int property = Config.DATA.getValue1();
答案 4 :(得分:1)
如果您在Java中执行此操作,我会将所有配置放在Spring中,然后使用Application Context查找设置或只是将它们注入您的bean。春天擅长这种事情。
答案 5 :(得分:1)
我们将您的属性设置为系统属性。这些是由SystemProperties
类访问的。
这个类是final
,带有一个私有构造函数,属性只能通过静态方法访问,所以从技术上来说它是一个Singleton。它本身包含在commons.jar中,其他每个项目都依赖于它。
所以没有必要传递任何东西,因为设置可以直接在您需要的地方使用。
答案 6 :(得分:0)
我肯定会让配置持有者类成为Singleton!我是Singleton实例的经典用例。
答案 7 :(得分:0)
配置没有,但最好有一个单例对象ServerManager
。太多全局可访问的对象有点令人困惑。配置应由“组件”拥有:
ServerManager.getServerManager.getConfigurationComponent(Configuration.class);
ServerManager应该在开始时创建和读取配置对象。离开之前保存并关闭它。
如果您在任何课程中多次使用它,请将其存储为私人最终字段。
答案 8 :(得分:0)
我经常使用它。我做了多个产品安装,但它们并不总是在同一个地方。但是,产品的安装,集成和实施通常是相同的。因此,为了弥补这一点,我编写了一个配置属性类,它查看了config.properties文件。您将进入并首先将属性文件修改为您需要的位置,值等等。然后使用config类编译该类,并使用该应用程序执行该操作。
以下示例。 config.properties文件
import_dir=c:\\temp\\test\\import
export_dir=c:\\temp\\test\\export
system_dir=c:\\temp\\test\\system
username=mainman
role=admin
domain=
server=
hostname=
等...
然后我在班上创建了一个班级。
public static class Config {
private static Properties defaultProps = new Properties();
static {
try {
FileInputStream in = new FileInputStream("config.properties");
defaultProps.load(in);
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getProperty(String key) {
return defaultProps.getProperty(key);
}
}
我相信你也可以创建一个独立课程,但这也可以。
然后在我的方法内部,或在主类中,我得到我需要的值,并将它们分配给我需要的任何东西。然后我可以将它们传递给需要它们的相应方法。
domain = Config.getProperty("domain");
server = Config.getProperty("server");
hostname = Config.getProperty("hostname");
非常酷!
我也在多个操作系统上使用它。