为什么在Struts 1.2.7中对MessageResourcesFactory进行延迟实例化?

时间:2009-07-27 09:33:31

标签: java struts lazy-loading eager-loading

由于存在Double-checked锁定问题,因此我们必须使用同步来保证对以下方法的并发访问(org.apache.struts.util.MessageResources类):

懒惰的实施

public synchronized static MessageResources getMessageResources(String config) {

    if (defaultFactory == null) {
        defaultFactory = MessageResourcesFactory.createFactory();
    }

    return defaultFactory.createResources(config);
}

为什么不使用:

EAGER INSTANTIATION

static {

    // Construct a new instance of the specified factory class
    try {
        if (clazz == null)
            clazz = RequestUtils.applicationClass(factoryClass);
        MessageResourcesFactory defaultFactory =
            (MessageResourcesFactory) clazz.newInstance();
    } catch (Exception e) {
        LOG.error("MessageResourcesFactory.createFactory", e);
    }

}

然后:

public static MessageResources getMessageResources(String config) {

    return defaultFactory.createResources(config);
}

它允许并发访问方法getMessageResources,至少在我的情况下可能会被调用很多次。

不使用synchronized时的含义在这里:

http://en.wikipedia.org/wiki/Double-checked_locking

4 个答案:

答案 0 :(得分:1)

MessageResourcesFactory线程安全吗? synchronized方法可以保护字段设置和createResources方法调用。如果它是线程安全的,则可以移动锁定以覆盖仅设置字段并将方法调用留在临界区之外。

答案 1 :(得分:0)

现代JVM上的同步方法所产生的开销非常小,以致无法实现。对调试同步的lazy-init工厂方法的后续调用将与调用非同步的eager-init方法一样快。

就代码而言,与使用静态初始化程序块相比,lazy-init方法更简单,更容易理解(在我看来)。此外,当静态初始化块失败时,弄清楚何处和原因可能会非常混乱。

答案 2 :(得分:0)

除非有任何理由MessageResourceFactory不能在早期初始化(例如,某些Servlet资源需要先初始化),我想我更喜欢你的解决方案。我猜想Struts团队没有理由懒洋洋地加载工厂,而不是特定的开发人员习惯这样做(人们确实倾向于懒散地加载单例,即使没有必要)。

您是否尝试过提交错误报告并提出解决方案?

答案 3 :(得分:0)

我认为这是Struts确保在多线程模式下工作正常的一种方式,无论覆盖org.apache.struts.util.MessageResources的人是否将createResources(String配置)定义为已同步