我有一个看起来像这样的课程:
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"
是否正确,或者这无关紧要?我正确设置静态属性吗?我还需要做什么或考虑一下吗?提前谢谢。
答案 0 :(得分:11)
Singleton作为设计模式与Spring的单例设施有一些区别。 Singleton作为设计模式将确保每个Class Loader定义一个类对象。相比之下,Spring的单例工具(和方法)将为每个Spring Context定义一个实例。
在这种情况下,您可以利用Spring使用的getInstance()
方法来获取对象实例:
<bean id="configurator" class="com.me.myapp.Configurator" factory-method="getInstance">
</bean>
使用Spring,singleton
bean作用域是默认的,因此您无需定义它。
如果要将configurator
用作Spring bean,则必须将其注入其他对象,而不是使用getInstance()
来获取它。所以在其他Spring bean中使用@Autowired或通过xml文件定义bean的引用。如果你没有重新组织其他类中configurator
的使用,那就没有区别,Spring将实例化你的类,但你将像以前一样使用它。
我也看到你在设计单身时遇到错误。您的getInstance()
方法应该是公开的,其他方法不应该是静态的。在您使用的示例中,您应该像这样使用Singleton:
Configurator.getInstance().someMethod()
在这种情况下,您实际上只使用Singleton类,而不实例化任何对象!有关Singleton设计模式以及如何使用它的更多信息,请参阅wikipedia on Singleton (with Java example)。
<小时/> 注意:值得了解并尝试将
Configurator
用作Singleton并使用Spring的单例工具。如果你这样做,那么你可以
getInstance()
方法答案 1 :(得分:1)
默认情况下,豆是单身。您可以通过spring网站找到这个/更多信息。
你不应该在getInstance中实例化一个新的Configurator,因为它不会引用spring加载的bean,这可能会导致一些严重的问题。您可以将此bean连接起来然后不管它,它不会为空,因为您已将其连接(如果您的程序初始化失败)。
答案 2 :(得分:0)
是的,如果你想要全球性的东西,单身范围是正确的选择。 这里值得一提的是:
答案 3 :(得分:0)
顺便说一句:这不是线程安全的:
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。