Spring注入一个静态(全局)单例

11 java singleton spring dependency-injection

我有一个看起来像这样的课程:

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
}
Run Code Online (Sandbox Code Playgroud)

它可以作为一个全局配置对象,可以在应用程序启动时设置,然后在整个项目中由几十个类使用:

// 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
    }
}
Run Code Online (Sandbox Code Playgroud)

我现在将此代码导入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>
Run Code Online (Sandbox Code Playgroud)

这样,当WidgetFactory#doSomething执行时,Spring将已经加载了Configurator类并提前配置它.

设置它是否正确scope="singleton",或者这不重要吗?我正确设置静态属性吗?我还需要做什么或考虑一下吗?提前致谢.

par*_*lov 11

Singleton作为设计模式与Spring的单例设施有一些区别.Singleton作为设计模式将确保每个Class Loader定义一个类对象.相比之下,Spring的单例工具(和方法)将为每个Spring Context定义一个实例.

在这种情况下,您可以利用getInstance()Spring 使用的方法来获取对象实例:

<bean id="configurator" class="com.me.myapp.Configurator" factory-method="getInstance">
</bean>
Run Code Online (Sandbox Code Playgroud)

使用Spring,singletonbean范围是默认值,因此您无需定义它.

如果你想configurator用作Spring bean,你必须将它注入其他对象,而不是getInstance()用来抓取它.所以在其他Spring bean中使用@Autowired或通过xml文件定义bean的引用.如果你没有重新组织configurator其他类的用法,那就没有区别,Spring将实例化你的类,但你将像以前一样使用它.

我也看到你在设计你的单身人士时遇到了错误.您的getInstance()方法应该是公共的,其他方法不应该是静态的.在您使用的示例中,您应该像这样使用Singleton:

Configurator.getInstance().someMethod()
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您实际上只使用Singleton类,而无需实例化任何对象!有关Singleton设计模式以及如何使用它的更多信息,请参阅Singleton上的wikipedia(带有Java示例).


注意:值得了解并尝试使用ConfiguratorSingleton并使用Spring的单例工具.如果你这样做,你可以获得好处

  • 删除getInstance()方法
  • 让你的构造函数公开
  • 让Spring实例化那个单个对象.