Spring 上下文未加载
Spring Context not loaded
我正在尝试将我的一个旧项目从 Spring 3.0.3.RELEASE 迁移到 4.0.9.RELEASE。我将 pom.xml 依赖项更改为 4.0.9,从那一刻起我就遇到了问题。 DispatcherServlet 无法在应用程序上下文中找到 bean。
以下是我的文件
web.xml
<context-param>
<param-name>bootstrapConfig</param-name>
<param-value>
/com/core/choreographer/bootstrap/bootstrap-config.xml
</param-value>
</context-param>
<listener>
<listener-class>
com.core.bootstrap.BootstrapManager
</listener-class>
</listener>
<listener>
<listener-class>com.spring.http.SpringHttpContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>http-remoting</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:com/remote/springhttp-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>http-remoting</servlet-name>
<url-pattern>/remoting/*</url-pattern>
</servlet-mapping>
bootstrap-config.xml 具有要插入到 spring 上下文中的所有 bean。它由 BootstrapManager 读取,是 ServletContextListener 的子项,并插入到 spring 上下文中。如下
public class BootstrapManager implements ServletContextListener
{
public void contextInitialized( ServletContextEvent ctxEvt )
{
URL cfgURL = "location to the xml file" ;
ServletContext context = ctxEvt.getServletContext() ;
bootstrap.initialize( cfgURL ) ;
}
}
public class Bootstrap
{
public void initialize( final URL cfgURL ) throws BootstrapException
{
XMLConfiguration config = new XMLConfiguration() ;
URL dtdURL = ReflectionUtil.getResource( Bootstrap.class, "bootstrap-config.dtd" ) ;
// register it at the configuration
config.registerEntityId( "-//Bootstrap//DTD 1.0//EN", dtdURL ) ;
config.setValidating( true ) ;
config.setURL( cfgURL ) ;
config.load() ;
initBootstrapElements( config ) ;
}
private void initBootstrapElements( final XMLConfiguration config ) throws BootstrapException
{
HierarchicalConfiguration cfg = null ;
int numElements = config.getList( "bootstrap-element[@class]" ).size() ;
for( int i = 0 ; i < numElements ; i++ )
{
cfg = config.configurationAt( "bootstrap-element(" + i + ")" ) ;
initElement( cfg ) ;
}
}
public void initElement( final HierarchicalConfiguration config ) throws BootstrapException
{
String className = null ;
String propName = null ;
Object propVal = null ;
HierarchicalConfiguration propCfg = null ;
BootstrapElement element = null ;
className = config.getString( "[@class]" ) ;
element = (BootstrapElement) ReflectionUtil.createInstance( className.trim() ) ;
beanWrapper.setWrappedInstance( element ) ;
int numProps = config.getList( "property[@name]" ).size() ;
for( int i = 0 ; i < numProps ; i++ )
{
propCfg = config.configurationAt( "property(" + i + ")" ) ;
propName = propCfg.getString( "[@name]" ) ;
propVal = propCfg.getProperty( "[@value]" ) ;
if( propVal == null )
{
propVal = propCfg.getList( "value" ) ;
}
beanWrapper.setPropertyValue( propName, propVal ) ;
}
element.initialize() ;//This called the below new ClassPathXmlApplicationContext(
}
}
ClassPathXmlApplicationContext appCtx = new ClassPathXmlApplicationContext( (String []) cfgLocations.toArray( new String [ 0 ] ) ) ;
然后我有一个 ContextLoaderListener
public class SpringHttpContextLoaderListener extends ContextLoaderListener {
private ContextLoader loader;
protected ContextLoader createContextLoader() {
loader = new SpringHttpContextLoader();
return loader;
}
public ContextLoader getContextLoader(){
return loader;
}
}
这是上下文加载器
public class SpringHttpContextLoader extends ContextLoader {
protected ApplicationContext loadParentContext(ServletContext servletContext)
throws BeansException {
SpringObjectFactory fact = BaseSpringObjectFactory.getInstance();
return fact.getApplicationContext();
}
}
这一切在 Spring 3.0.3 中都运行良好。当我试图将所有 Jar 替换为 4.0.9 时。 springhttp-servlet.xml 中定义的 Beans 无法找到 bootstrap-config.xml.[=15= 中定义的 bean ]
非常感谢任何建议。过去 2-3 周以来,我一直被困在这个问题上。
我发现了 SpringHttpContextLoaderListener
的问题。它覆盖了 createContextLoader
和 getContextLoader
的方法 deprecated in Spring version 3 所以被删除了在 Spring 版本 4 中。因此,自定义上下文未作为父上下文加载。
public class SpringHttpContextLoaderListener extends ContextLoaderListener {
private ContextLoader loader;
protected ContextLoader createContextLoader() {
loader = new SpringHttpContextLoader();
return loader;
}
public ContextLoader getContextLoader(){
return loader;
}
}
解决方案
在 class SpringHttpContextLoaderListener
中覆盖 class ContextLoader
的 loadParentContext
protected ApplicationContext loadParentContext(ServletContext servletContext)
throws BeansException {
SpringObjectFactory fact = BaseSpringObjectFactory.getInstance();
return fact.getApplicationContext();
}
这会将自定义创建的 Context 设置为父级,并将对所有 child context
可用
如果您要迁移到 spring 4,则无需执行其中大部分操作。当 AbstractAnnotationConfigDispatcherServletInitializer 加载上下文 spring 和应用程序上下文时。
我正在尝试将我的一个旧项目从 Spring 3.0.3.RELEASE 迁移到 4.0.9.RELEASE。我将 pom.xml 依赖项更改为 4.0.9,从那一刻起我就遇到了问题。 DispatcherServlet 无法在应用程序上下文中找到 bean。
以下是我的文件
web.xml
<context-param>
<param-name>bootstrapConfig</param-name>
<param-value>
/com/core/choreographer/bootstrap/bootstrap-config.xml
</param-value>
</context-param>
<listener>
<listener-class>
com.core.bootstrap.BootstrapManager
</listener-class>
</listener>
<listener>
<listener-class>com.spring.http.SpringHttpContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>http-remoting</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:com/remote/springhttp-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>http-remoting</servlet-name>
<url-pattern>/remoting/*</url-pattern>
</servlet-mapping>
bootstrap-config.xml 具有要插入到 spring 上下文中的所有 bean。它由 BootstrapManager 读取,是 ServletContextListener 的子项,并插入到 spring 上下文中。如下
public class BootstrapManager implements ServletContextListener
{
public void contextInitialized( ServletContextEvent ctxEvt )
{
URL cfgURL = "location to the xml file" ;
ServletContext context = ctxEvt.getServletContext() ;
bootstrap.initialize( cfgURL ) ;
}
}
public class Bootstrap
{
public void initialize( final URL cfgURL ) throws BootstrapException
{
XMLConfiguration config = new XMLConfiguration() ;
URL dtdURL = ReflectionUtil.getResource( Bootstrap.class, "bootstrap-config.dtd" ) ;
// register it at the configuration
config.registerEntityId( "-//Bootstrap//DTD 1.0//EN", dtdURL ) ;
config.setValidating( true ) ;
config.setURL( cfgURL ) ;
config.load() ;
initBootstrapElements( config ) ;
}
private void initBootstrapElements( final XMLConfiguration config ) throws BootstrapException
{
HierarchicalConfiguration cfg = null ;
int numElements = config.getList( "bootstrap-element[@class]" ).size() ;
for( int i = 0 ; i < numElements ; i++ )
{
cfg = config.configurationAt( "bootstrap-element(" + i + ")" ) ;
initElement( cfg ) ;
}
}
public void initElement( final HierarchicalConfiguration config ) throws BootstrapException
{
String className = null ;
String propName = null ;
Object propVal = null ;
HierarchicalConfiguration propCfg = null ;
BootstrapElement element = null ;
className = config.getString( "[@class]" ) ;
element = (BootstrapElement) ReflectionUtil.createInstance( className.trim() ) ;
beanWrapper.setWrappedInstance( element ) ;
int numProps = config.getList( "property[@name]" ).size() ;
for( int i = 0 ; i < numProps ; i++ )
{
propCfg = config.configurationAt( "property(" + i + ")" ) ;
propName = propCfg.getString( "[@name]" ) ;
propVal = propCfg.getProperty( "[@value]" ) ;
if( propVal == null )
{
propVal = propCfg.getList( "value" ) ;
}
beanWrapper.setPropertyValue( propName, propVal ) ;
}
element.initialize() ;//This called the below new ClassPathXmlApplicationContext(
}
}
ClassPathXmlApplicationContext appCtx = new ClassPathXmlApplicationContext( (String []) cfgLocations.toArray( new String [ 0 ] ) ) ;
然后我有一个 ContextLoaderListener
public class SpringHttpContextLoaderListener extends ContextLoaderListener {
private ContextLoader loader;
protected ContextLoader createContextLoader() {
loader = new SpringHttpContextLoader();
return loader;
}
public ContextLoader getContextLoader(){
return loader;
}
}
这是上下文加载器
public class SpringHttpContextLoader extends ContextLoader {
protected ApplicationContext loadParentContext(ServletContext servletContext)
throws BeansException {
SpringObjectFactory fact = BaseSpringObjectFactory.getInstance();
return fact.getApplicationContext();
}
}
这一切在 Spring 3.0.3 中都运行良好。当我试图将所有 Jar 替换为 4.0.9 时。 springhttp-servlet.xml 中定义的 Beans 无法找到 bootstrap-config.xml.[=15= 中定义的 bean ]
非常感谢任何建议。过去 2-3 周以来,我一直被困在这个问题上。
我发现了 SpringHttpContextLoaderListener
的问题。它覆盖了 createContextLoader
和 getContextLoader
的方法 deprecated in Spring version 3 所以被删除了在 Spring 版本 4 中。因此,自定义上下文未作为父上下文加载。
public class SpringHttpContextLoaderListener extends ContextLoaderListener {
private ContextLoader loader;
protected ContextLoader createContextLoader() {
loader = new SpringHttpContextLoader();
return loader;
}
public ContextLoader getContextLoader(){
return loader;
}
}
解决方案
在 class SpringHttpContextLoaderListener
ContextLoader
的 loadParentContext
protected ApplicationContext loadParentContext(ServletContext servletContext)
throws BeansException {
SpringObjectFactory fact = BaseSpringObjectFactory.getInstance();
return fact.getApplicationContext();
}
这会将自定义创建的 Context 设置为父级,并将对所有 child context
可用如果您要迁移到 spring 4,则无需执行其中大部分操作。当 AbstractAnnotationConfigDispatcherServletInitializer 加载上下文 spring 和应用程序上下文时。