我有一个看起来像这样的课程:
public class Configurator {
private static Configurator INSTANCE = null;
private int maxRange = 1;
// many other properties; each property has a default value
private static synchronized Configurator getInstance() {
if(INSTANCE == null)
return new Configurator();
return INSTANCE;
}
public static int getMaxRange() {
getInstance().maxRange;
}
public static void setMaxRange(int range) {
getInstance().maxRange = range;
}
// Getters and setters for all properties follow this pattern
}
它可以作为一个全局配置对象,可以在应用启动时设置,然后在整个项目中由几十个类使用:
// Called at app startup to configure everything
public class AppRunner {
Configurator.setMaxRange(30);
}
// Example of Configurator being used by another class
public class WidgetFactory {
public void doSomething() {
if(Configurator.getMaxRange() < 50)
// do A
else
// do B
}
}
我现在将此代码导入Spring项目,并尝试配置我的Sprinig XML(bean)。我的猜测是我可以定义一个孤独的 Configurator
像这样的bean(或类似的东西):
<bean id="configurator" class="com.me.myapp.Configurator" scope="singleton">
<property name="maxRange" value="30"/>
<!-- etc., for all properties -->
</bean>
那样的话 WidgetFactory#doSomething
执行,Spring将已经加载了 Configurator
类并提前配置它。
设置它是否正确 scope="singleton"
,或者这不重要吗?我正确设置静态属性吗?我还需要做什么或考虑一下吗?提前致谢。
Singleton作为设计模式与Spring的单身设施有一些区别。 Singleton作为设计模式将确保每个Class Loader定义一个类对象。相比之下,Spring的单例工具(和方法)将为每个Spring Context定义一个实例。
在这种情况下,您可以利用您的 getInstance()
Spring用来抓取你的对象实例的方法:
<bean id="configurator" class="com.me.myapp.Configurator" factory-method="getInstance">
</bean>
随着春天 singleton
bean范围是默认值,因此您无需定义它。
如果你想使用 configurator
作为一个Spring bean,你必须将它注入其他对象,而不是使用它 getInstance()
抓住它。所以在其他Spring bean中使用@Autowired或通过xml文件定义bean的引用。如果你不重新组织使用 configurator
在其他类中,没有区别,Spring会实例化你的类,但你会像以前一样使用它。
我也看到你在设计你的单身人士时遇到了错误。你的 getInstance()
方法应该是公共的,其他方法不应该是静态的。在您使用的示例中,您应该像这样使用Singleton:
Configurator.getInstance().someMethod()
在这种情况下,您实际上只使用Singleton类,而无需实例化任何对象!看到 Singleton上的维基百科(附Java示例) 有关Singleton设计模式以及如何使用它的更多信息。
注意:值得了解并尝试使用
Configurator
作为一个单身人士并使用Spring的单身人士设施。如果你这样做,你可以获得好处
- 去除
getInstance()
方法
- 让你的构造函数公开
- 让Spring实例化那个单个对象。
Singleton作为设计模式与Spring的单身设施有一些区别。 Singleton作为设计模式将确保每个Class Loader定义一个类对象。相比之下,Spring的单例工具(和方法)将为每个Spring Context定义一个实例。
在这种情况下,您可以利用您的 getInstance()
Spring用来抓取你的对象实例的方法:
<bean id="configurator" class="com.me.myapp.Configurator" factory-method="getInstance">
</bean>
随着春天 singleton
bean范围是默认值,因此您无需定义它。
如果你想使用 configurator
作为一个Spring bean,你必须将它注入其他对象,而不是使用它 getInstance()
抓住它。所以在其他Spring bean中使用@Autowired或通过xml文件定义bean的引用。如果你不重新组织使用 configurator
在其他类中,没有区别,Spring会实例化你的类,但你会像以前一样使用它。
我也看到你在设计你的单身人士时遇到了错误。你的 getInstance()
方法应该是公共的,其他方法不应该是静态的。在您使用的示例中,您应该像这样使用Singleton:
Configurator.getInstance().someMethod()
在这种情况下,您实际上只使用Singleton类,而无需实例化任何对象!看到 Singleton上的维基百科(附Java示例) 有关Singleton设计模式以及如何使用它的更多信息。
注意:值得了解并尝试使用
Configurator
作为一个单身人士并使用Spring的单身人士设施。如果你这样做,你可以获得好处
- 去除
getInstance()
方法
- 让你的构造函数公开
- 让Spring实例化那个单个对象。
豆是默认的单身。您可以通过spring网站找到这个/更多信息。
你不应该在getInstance中实例化一个新的Configurator,因为它不会引用spring加载的bean,这可能会导致一些严重的问题。您可以将此bean连接起来然后不管它,它不会为空,因为您已将其连接(如果您的程序将初始化失败)。
是的,如果你想要全球性的东西,单身范围是正确的选择。
这里值得一提的是:
- spring中的默认范围是singleton,因此您不需要
显式地将bean设置为单例范围。
- 使用Spring,您不需要编写 单身人士模式 样式代码,例如私有实例和工厂方法。那是因为春天会
保证每个Spring只有一个实例
容器。甚至没有说,你的工厂方法是私人的。
顺便说一句:这不是线程安全的:
if(INSTANCE == null)
return new Configurator();
return INSTANCE;
}
这将是:
private static Configurator INSTANCE = new Configurator();
(急切初始化)
private static volatile Singleton _instance = null;
(使用volatile关键字进行延迟初始化)
它与Java分配内存和创建实例的方式有关。这不是原子的,而是分两步完成,可以受到线程调度程序的干扰。
也可以看看 http://regrecall.blogspot.de/2012/05/java-singleton-pattern-thread-safe.html。