我试图在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。
感谢大家的任何建议。
此致 达尼洛。
答案 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。