静态方法中的Spring上下文为null

时间:2016-02-01 16:43:23

标签: java spring spring-mvc hybris

我试图在Spring MVC中使用spring Application Context - Hybris Application,但它始终是null。

public class FlexSelector{
protected static final ApplicationContext ctx = Registry.getApplicationContext();

protected static final PropertiesReader getPropertiesReader(){
return (PropertiesReader) ctx.getBean("serviceExtensionPropertiesReader");
}

protected static final SearchRestrictionService getSearchRestrictionService(){
return (SearchRestrictionService) ctx.getBean("searchRestrictionService");
} 
   protected static final FlexibleSearchService getFlexibleSearchService(){
return (FlexibleSearchService) ctx.getBean("flexibleSearchService");
}

    protected static final <T> T getModelByExample(T example) {
return getFlexibleSearchService().getModelByExample(example);
} .....}

有这个课程:

public class CustomerSelector extends FlexSelector {

public final static CustomerModel getCustomerByEmail(String email){
CustomerModel filter = new CustomerModel();
filter.setUid(email);
return getModelByExample(filter);
}

}

我现在的工作是移植Hybris版本。 当我尝试调用CustomerSelector.GetCustomerByEmail("test@gmail.com")它会引发异常,因为此类中使用的上下文ctx始终为null。 感谢大家的任何建议。

此致 达尼洛。

2 个答案:

答案 0 :(得分:2)

存储对Spring对象的静态引用并不是一个好主意,几乎总会导致问题。 真正的问题不是存储对Spring对象的引用,而是在类加载时将其分配给静态变量。以下是发生的事情:

protected static final ApplicationContext ctx = Registry.getApplicationContext();

这是FlexSelector类中的静态字段,因此在类加载器加载类时会初始化它。假设到目前为止,Spring上下文已准备好为您提供正确的引用,这非常危险。总是获得空值实际上是一个非常好的结果。它可能会更糟糕,它可能会导致间歇性(!)NoClassDefFoundError-s偶尔在Spring层中尝试获取所需的bean时发生异常。既然你没有加载一个特定的bean,那么你只需要使用至少一个常量null的上下文,这样就可以了。

可能的解决方案:

  • 您没有理由持有对ApplicationContext的静态引用。每次使用时都会获得它,它会正常工作。

  • 如果你必须这样做,至少要懒洋洋地获得它。 在某些情况下它可以正常工作,尽管它仍然不是最好的主意。如果你使用它,你只需要声明你的ctx变量非final,然后总是通过getter访问它。如果它尚未初始化,则在第一次尝试时初始化它。这需要对代码进行很少的更改,但我仍然会选择第一个选项。

答案 1 :(得分:1)

在此处查看我的回答:https://stackoverflow.com/a/34943282/932201 您不应该对应用程序上下文有静态引用。

您是否可以控制FlexSelector课程并可以更改?

如果是,请在上面的答案中进行修改,否则我可能会重新实现FlexSelector课程。

让它更加“弹性化”#34;我一般会将FlexSelector声明为bean,而不是protected static final方法,只是protected并且还通过FlexibleSearchService注入其他bean,如@Required等注释或在myextension-spring.xml文件声明中。

如果您无法对FlexSelector进行任何更改,快速解决方案也可以直接在CustomerSelector中查找flexibleSearchService:

    final FlexibleSearchService flexiService = (FlexibleSearchService) Registry.getApplicationContext().getBean("flexibleSearchService");
    CustomerModel filter = new CustomerModel();
    filter.setUid(email);
    return flexiService.getModelByExample(filter);

这在运行时查找flexiblesearch bean的运行时成本较低,但它至少应该可以帮助你绕过NPE。